美文网首页Android开发Android开发经验谈Android技术知识
Android卡顿优化 | 卡顿及其优化工具概述及StrictM

Android卡顿优化 | 卡顿及其优化工具概述及StrictM

作者: 凌川江雪 | 来源:发表于2020-03-31 22:43 被阅读0次

    项目GitHub

    本文要点

    • 一般使用的卡顿优化工具
    • 卡顿问题概述
    • 卡顿问题分析难点
    • 关于CPU Profiler
    • 关于Systrace
    • 关于StrictMode
    • 磁盘读写违例检测实战
    • 实例限制检测实战

    一般使用的卡顿优化工具

    • CPU Profiler
    • Systrace
    • StrictMode
      (strict adj.精确的; 绝对的; 严格的,严谨的; [植]笔直的
      mode n.方式; 状况; 时尚,风尚; 调式 模式;)

    卡顿问题概述

    • 很多性能问题(如内存占用高、耗费流量等)都相对不容易被发现,
      但是卡顿问题却是很容易被直观感受到的;
    • 卡顿问题较难排查、定位;

    卡顿问题分析难点

    • 可能的产生原因 繁杂:代码、内存、绘制、IO、【在主线程做UI处理、IO操作耗时操作】等;
    • 线上卡顿问题,在线下难以复现,
      卡顿问题跟用户届时的现场环境有很大的关系;
    • 比如,
      届时用户终端的磁盘IO空间不足,影响了APP的IO写入性能,
      导致APP卡顿,这样的场景有时候是很难复现的;
      【最好在问题发生时候,就记录下来用户届时的场景】

    关于CPU Profiler

    • 图形的形式展示程序的执行时间、调用栈、执行次数等;

    • 信息全面,包含了所有线程、所有方法的调用时间;

    • 运行时开销比较严重,导致APP运行时所有函数都会不等比地变慢,可能会带偏优化方向;

    • 使用方式

      • Debug.startMethodTracing();【在需要监控的代码块前添加(注意它有四个重载方法)】
      • Debug.stopMethodTracing();【在需要监控的代码块后添加】
      • 生成的调试文件在sd卡:Android/data/packagename/files
      • 上次在内存优化的实战中,
        其实已经使用过,提到过CPU Profiler了,
        这里可以看一下App内存优化 之 内存抖动解决实战!!!!!!

    关于Systrace

    关于StrictMode

    • 严苛模式,Android提供的一种运行时检测机制;
      如果在开发阶段对成千上万行的代码进行code review,
      可能效率是比较低下的;
      使用StrictMode之后,
      系统会自动检测出来主线程当中违例的一些情况,
      同时按照代码的配置给出相应的反应

    • 方便,强大,容易被忽视

    • 主要检测:线程检测策略、虚拟机检测策略

      • 线程检测策略【StrictMode.setThreadPolicy()】:
        如,
        自定义的耗时调用检测,如detectCustomSlowCalls()
        磁盘读取操作检测,detectDiskReads()
        网络操作检测,detectNetwork()
        【detect vt.查明,发现; 洞察; 侦察,侦查; 】
      • 虚拟机策略【StrictMode.setVmPolicy()】:
        Activity泄漏检测,detectActivityLeaks()
        SqlLite对象泄漏检测,detectLeakedSqlLiteObjects()
        限制实例数量检测,setClassInstanceLimit(要限制的类实例,限制的数量)
    • 具体使用:
      可以在Activity或者ApplicationonCreate()中调用StrictMode的方法:

    private boolean DEV_MODE = true;
    
        private void initStrictMode() {
            if (DEV_MODE) {
                StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                        .detectCustomSlowCalls() //API等级11,使用StrictMode.noteSlowCode
                        .detectDiskReads()
                        .detectDiskWrites()
                        .detectNetwork()// or .detectAll() for all detectable problems
                        .penaltyLog() //在Logcat 中打印违规异常信息
                        .build());
    
                StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                        .detectLeakedSqlLiteObjects()
                        .setClassInstanceLimit(NewsItem.class, 1)
                        .detectLeakedClosableObjects() //API等级11
                        .penaltyLog()
                        .build());
            }
        }
    
    • 【调试技巧】
      设置一个DEV_MODE标志位:
      只有在线下开发的环境时将之设置为true,才会使进程打开StrictMode

    • 【检测策略的调用】
      detect开头的方法,
      都是StrictMode提供的检测策略,
      调用过了,则StrictMode便会进行相应的检测和反应;

    • 【响应方式配置】
      penaltyLog()【penalty n.惩罚,刑罚,害处】是出现违规后用log打印出来,即指定StrictMode的响应方式,
      StrictMode除了打印log的方式,
      还有其他响应方式,
      penaltyDeath()可以让APP直接崩溃掉,
      penaltyDialog()可以弹出一个Dialog等!!!!!!!!!

    • 实战一下:
      磁盘读写违例检测(log的响应方式):

    /**
     * 模拟内存泄露的Activity
     */
    public class MemoryLeakActivity extends AppCompatActivity implements CallBack{
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_memoryleak);
    
            ImageView imageView = findViewById(R.id.iv_memoryleak);
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.splash);
            imageView.setImageBitmap(bitmap);
    
            CallBackManager.addCallBack(this);
    
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .penaltyLog()
                    .build());
    
            findViewById(R.id.iv_memoryleak).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    writeToExternalStorage();
                }
            });
        }
    
        /**
         * 文件系统的操作
         */
        public void writeToExternalStorage() {
            try {
                File externalStorage = Environment.getExternalStorageDirectory();
    
                File mbFile = new File(externalStorage, "xxx.txt");
                if (mbFile.exists()){
                    mbFile.createNewFile();
                }
    
                OutputStream output = new FileOutputStream(mbFile, true);
                output.write("www.wooyun.org".getBytes());
                output.flush();
                output.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            CallBackManager.removeCallBack(this);
        }
    
        @Override
        public void dpOperate() {
            // do sth
        }
    }
    
    Dialog的响应方式:

    以上IO违例的原因就是在主线程做了IO操作了
    这显然是不行的,需要开一个子线程给它整!

    • 实例限制检测:
    public class TestApp extends Application {
    
        static MemoryLeakActivity i = new MemoryLeakActivity();
        static MemoryLeakActivity j = new MemoryLeakActivity();
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            //实例限制检测 测试
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                    .setClassInstanceLimit(MemoryLeakActivity.class, 1)
                    .detectLeakedClosableObjects() //API等级11
                    .penaltyLog()
                    .build());
        }
    }
    









    相关文章

      网友评论

        本文标题:Android卡顿优化 | 卡顿及其优化工具概述及StrictM

        本文链接:https://www.haomeiwen.com/subject/bszpuhtx.html