你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

Android性能优化篇

2021/12/22 16:09:49

1.减少APK体积

1.删除无用资源

可通过lint扫描出无用资源,直接删除。

2.删除重复资源

通过python等脚本扫描出MD5值一样的图片或者、xml资源进行删除。

3.过大图片压缩

通过python等脚本扫描出多大图片进行图片压缩。

4.so库只加入指定平台

比如只加入armeabi、armeabi-v7a平台。

5.开启代码混淆与资源压缩

资源压缩、代码混淆一定程度上能减少些APK大小。

 debug {
            minifyEnabled true //代码混淆
            shrinkResources true //资源压缩
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }

2.启动优化

冷启动:启动时,后台没有任何该应用的进程,系统需要重新创建一个进程,并结合启动参数启动该应用。

热启动:启动时,系统已经有该应用的进程(比如按 home 键临时退出该应用)下启动该应用。

 1.开启异步线程处理耗时操作

比如IO操作、sqlite初始化、一些其他第三方库的初始化等

2.检查并去除没必要启动时候初始化的逻辑

比如一些业务逻辑、一些工具类的初始化,可以在使用时初始化,没必要在启动时就初始化

3.闪屏页优化

设置闪屏页windowBackground图片,这样启动窗口的图片就会是闪屏页图片,而不是白屏。

闪屏页广告图片首次安装app打开后不加载到下载存储到本地,第二次启动再加载。

3.Crash与ANR

1.异常处理

接入bugly等第三方捕获异常平台,或者定义自己的UncaughtExceptionHandler将APP崩溃保存进文件并传给自己的服务器

2. ANR - 应用未响应

ANR 全称 Applicatipon No Response;Android 设计 ANR 的用意,是系统通过与之交互的组件(Activity,Service,Receiver,Provider)以及用户交互(InputEvent)进行超时监控,以判断应用进程(主线程)是否存在卡死或响应过慢的问题,通俗来说就是很多系统中看门狗(watchdog)的设计思想。

主要是通过 /data/anr 目录下面生成 traces.txt 文件,查找出相关Blocked、4大组件的anr日志等。可以接入爱奇艺XCrash、bugly上报 线上traces.txt文件。

4.内存优化

1.内存泄露工具

接入leackcanary到app中,开发、测试、产品验收、app发布前,尽最大努力处理掉内存泄漏问题。

2.内存泄漏场景

1) 单例导致内存泄露,单例Context要传getApplicationContext。

2) 静态变量导致内存泄露,静态变量存储在方法区,它的生命周期从类加载开始,到整个进程结束。一旦静态变量初始化后,它所持有的引用只有等到进程结束才会释放,同上Context问题。

3) 非静态内部类内存泄露,非静态内部类构造方法参数是外部类,所以在Activity中要定义静态内部类并使用。

4) Handler引起的内存泄漏,使用静态类+弱引用。

5) 广播、发布/订阅框架等注册后未取消注册引起的内存泄漏

6) IO、数据库Cursor等需要关闭的资源使用完未关闭引起的内存泄漏

7) 集合中的对象未清理造成内存泄露,集合中的对象如果已经没用,集合中还存在,则造成内存泄漏,要及时清除,如果集合是static修饰更容易出现此问题

8) 属性动画造成内存泄露,比如关闭Activity时,页面中属性动画依然会不断地播放下去,动画引用所在的控件,所在的控件引用Activity,这就造成Activity无法正常释放,所以Activity销毁的时候cancel掉属性动画,避免发生内存泄漏。

8) WebView造成内存泄露,在销毁WebView之前需要先将WebView从父容器中移除,然后在销毁WebView。

3.内存优化

1) bitmap尽量指定大小、尺寸去使用,能够复用的bitmap考虑复用

2) 尽可能少地创建对象,比如创建统一的线程池去处理异步操作、自定义 view 时不要在 onDraw 方法里面频繁创建对象、尽量用 StringBuilder 或者 StringBuffer 来拼接字符串等

5.卡顿优化

1.卡顿

操作过程中卡顿了,一般就是 CPU 和 GPU 其中的一个或者多个无法短时间完成对应的任务,CPU 造成卡顿更常见,一般也是通过减少 CPU 的计算任务来优化卡顿。

2.检查卡顿

1) 利用UI线程Looper打印的日志

public static void loop() {
    final Looper me = myLooper();

    final MessageQueue queue = me.mQueue;
    // ...
    for (;;) {
        Message msg = queue.next();
        
        //dispatchMessage之前
        Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }
        
        //dispatchMessage
        msg.target.dispatchMessage(msg);

        //dispatchMessage之后
        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        // ...
        }
    }
}

//设置Printer
Looper.getMainLooper().setMessageLogging(new Printer() {
       @Override
       public void println(String s) {
       }
});

Android中界面的刷新需要在主线程或者说 UI 线程执行,界面的绘制起始点又利用了 Looper 消息循环机制,通过设置Printer,可打印dispatchMessage方法执行时长。

2) 利用Choreographer

Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,可以通过Choreographer设置相关回调,两次回调的时间周期应该在16ms,如果超过了16ms则认为发生了卡顿,这里暂不深入。

2.影响 CPU 的使用率一般有以下几个方面

  • 读写文件,频繁多次读写文件操作,耗时且耗资源,要少做。比如SP尽量批量操作后apply 或者 commit.

  • 解析大量图片,解码图片毫无疑问是一个计算量大的操作。

1.加载图片的时候最好根据实际显示的尺寸做压缩,并且保存压缩后的缩略图,方便下次直接加载。

2.列表滑动不加载图片

3.对不同的图片格式,用不同的解码格式。比如 png 格式的图片根据机器实际情况选择 8888 或者 4444 解码方式解码图片。如果是 jpg/jpeg 格式的图片,就用 565 的解码方式解码图片。这操作是减少内存,防止内存不足,系统进行GC操作从而耗费资源与CPU。

  • 频繁请求网络,使用 okhttp 请求网络的话,尽量全局使用一个 httpclient ,这样做的好处是可以复用,提高网络请求效率。其他比如减少请求接口数量、自定义dns减少dns解析时间、传输采用gzip压缩数据等。

  • 复杂的布局,CPU 需要大量的运算资源,特别是布局层级太深要进行不断递归运算与绘制,所以优化复杂的布局是很有必要的。

  • 频繁创建对象,可能会短时间内消耗大量内存,然后内存不足的时候系统就会尝试 GC 来回收对象,而 GC 是很耗资源的操作。

参考文章

分享一波 Android 性能优化的总结!