App内存和性能优化

ANR(Application Not Responding)

5s程序无响应,主线程做耗时操作引起,也就是主线程被阻塞。

发生在主线程中的有:
Activity、Service、BroadcastReceiver的onReceive回调
主线程中new Handler();
view.post(Runnable)

解决方式:
使用AsyncTask处理耗时操作
使用Thread和HanlderThread提高优先级
Activity的生命周期回调中尽量不要做耗时操作

app申请的内存

每个app分配的最大内存限制,随不同设备而不同


切换应用时后台app清理机制:
LRU Cache机制:最近使用的排在最前面,最少可能的被清理
清理内存回调onTrimMemory方法

Java中的引用方式

强引用:对象强引用,当内存不足,虚拟机宁愿抛出OOM,也不会随意回收强引用
软引用(SoftReference):当内存不足时候,垃圾回收器才回收
弱引用(WeakReference):当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象
虚引用(PhantomReference):如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收
ps:被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在JVM进行垃圾回收时总会被回收...

** 优化方法**

数据结构的优化

  • 字符串的拼接用StringBuilder(替换频繁的String字符拼接等)
    字符串通过+的方式进行拼接会产生中间字符串内存块,这些都是没有用的。

  • ArryMap、SpareseArray替换HashMap
    因为ArryMap、SpareseArray内存占用少,且效率更高

  • 内存抖动
    一时间创建很多对象

  • Service使用完尽量停止

对象复用

1、复用系统自带资源
2.ListView相关复用
3.避免在onDraw中创建对象

避免内存泄露

代码问题导致这块内存,虽然停止使用,但依然
被其他对象引用这,使得GC没发对它回收

1.避免Activity泄露,用弱引用
2.引用Context时,能用Application尽量用Application

  • Context 泄漏, 主要为Activity 传递泄漏, context 未使用applciationConext 在单例创建时。
    • Handler 泄漏 , handler中持有view ,context 等做耗时操作。
    • Cursor 泄漏 , cursor未关闭
    • register 未 unregister
    • Bitmap
    • adapter 未使用convertView
    • WebView内存泄露
    • 不良代码等
WebView内存泄露解决方式:
    https://stackoverflow.com/questions/3130654/memory-leak-in-webview
    Android系统的一个bug:通过XML布局创建WebView时,活动作为WebView的上下文而不是应用程序上下文传递。 完成活动后,WebView仍然保持对活动的引用,因此活动不会从内存中移除。 必须使用new创建:
    WebView webView = new WebView(getApplicationContext());
    
    webView销毁:
    ```
    @Override
    protected void onDestroy() {
    super.onDestroy();
    if (null != mWebView) {
        //解除webView与父控件的依附关系
        ((ViewGroup) mWebView.getParent()).removeView(mWebView);
        mWebView.removeAllViews();
        mWebView.setTag(null);
        mWebView.clearHistory();
        mWebView.loadUrl("about:blank") ;
        mWebView.setVisibility(View.GONE);
        mWebView.destroy();
        mWebView = null;
        }
    }
    ```

资源使用完未关闭(BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap)

写完程序对程序进行Review,或者用代码检测工具检查,运行时候使用LeakCanary检查是否有内存泄露。内存紧张时释放一些图片内存等
如查询数据库的操作,使用到Cursor,也要对Cursor对象及时关闭
ndroid程序里面存在很多需要register与unregister的监听器,手动add的listener,需要记得及时remove这个listener。

强引用、软引用、弱引用

优化OOM

1.注意临时Bitmap对象的及时回收
2.加载Bitmap:缩放比例、解码格式、局部加载

性能优化

卡顿原理:
    60fps->16ms,如果16毫秒在60帧以下,就会卡顿

解决方式:
    不要在主线程中做轻微的耗时操作
    同一时间动画执行次数过多,导致CPU或GPU负载过重,要避免
    列表Adapter的复用
    布局优化:
        去除XML布局中不必要的bg设置
        减小View的层级,使用ViewStub
        避免嵌套过多无用布局,同样的层级LinearLayout优于RelativeLayout.
        merge标签的使用

冷启动:
    在启动应用前,系统中没有该应用的任何进程信息
    
    缩短冷启动时间:
    减少onCreate方法的工作量,使用懒加载加载第三方SDK
    
热启动:
    退出应用后,重启启动应用系统中有该应用的任何进程信息
    
[启动优化](http://www.jianshu.com/p/f5514b1a826c):
    Splash添加主题
    异步初始化第三方组件(使用IntentService开启后台线程初始化)

Bitmap

LRU(LruCache)算法:清除最近最少使用的Bitmap, put进去的时候有个putCount的计数器,可以判断putCount最小的就是最少使用的

计算inSampleSize

缩略图

三级缓存:先查内存--->SD卡--->网络请求

其他优化

不要使用静态变量存储数据

Shareprefrence:
    不能跨进程同步
    不能存储大数据,因为读写値会阻塞主线程,并且会产生大量临时对象,频繁GC导致内存抖动等等

APK瘦身

使用一套资源,且图片使用tinypng有损压缩
启动页使用jpg 720小图
webp图片使用
开启混淆代码
通过AS工具移除无用资源
删除无用语言资源
so包只使用armable目标(微信等大厂app都是这样)
避免重复库的使用,比如使用了两个图片加载库:Glide和Picasso
如果raw文件夹下有音频文件,尽量不要使用无损的音频格式,比如wav。可以考虑相比于mp3同等质量但文件更小的opus音频格式
多用代码实现UI,shape等

电量优化

及时停止定位
谨慎使用WakeLock

你可能感兴趣的:(App内存和性能优化)