Android优化相关总结

  • Post author:
  • Post category:其他




内存优化



内存优化的几种方法:


  1. 需要使用多少内存申请多少内存。

    • 比如实例化数组大小。
    • 创建Map时如果Key值支存在Int类型的话可以尝试使用SparseArray。
    • 加载图片的时候,在不需要特别高画质的情况下可以采用压缩或者使用占用内存较小的图片格式,如默认的图片格式是ARGB_8888可以换成RGB_565。

  2. 对象不再使用之后及时进行回收与关闭

    。比如Bitmap,一般Bitmap占用的内存都会比较大,虽然ImageView在回收后会自动释放Bitmap,但是这样可能存在一定时间的延后,大量的内存需要进行GC也可能导致系统停顿。另外需要注意的是Android3.0之前Bitmap对象的像素数据是存放在Native内存中的,所以需要手动调用recycler()进行内存回收,Android3.0之后内存全部存放在了Dalvik Heap中,这时就可以由虚拟机进行内存管理了。


  3. 预防内存泄漏的发生

    ,出现内存泄漏之后会导致申请的内存不能够被虚拟机回收,最后出现OOM的问题。


  4. 防止静态对象持有其它对象的引用,特别是静态的List或者Map对象。


  5. 广播或者其它第三方库在不需要使用后要记得进行反注册或者解绑。

比较常见的第三方库比如EventBus、Rxjava之类。


  1. 提高对象的复用利用率:

    1. Bitmap对象可以设置BitmapFactory.Options.inBitmap,Android4.4后只要被复用的Bitmap大于需要新申请内存的Bitmap即可。
    2. 减少方法中临时变量的创建。举个例子,如果在View的onDraw方法中初始化新的对象那么就将代表着每隔16ms都会实例化一个这个对象出来,因为正常情况下每隔16ms将会进行一个View的重新绘制。

  2. 清单文件中使用largeHeap=”true”属性来开启大内存



出现内存泄漏的原因与解决方法


  • Handler出现内存泄漏原因:

    1. Handler初始化使用的是匿名内部类的方式。
    2. Handler的初始化使用的是非静态内部类。

这几种方式都会隐式的含有一个父对象的引用,如果是在Activity中创建,就会导致Activity一直不能够回收。


  • Handler内存泄漏的解决方法:

    1. 使用静态的内部类创建Handler实例。
    2. 在Activity等组件中可以使用WeakReference引用相应的对象,这样不会影响GC的正常执行。

  • 单例模式导致的内存泄漏

我们在创建单例的静态对象的时候经常会需要一个Context对象,特别常见的是传入的是一个Activity对象,由于被静态对象强引用,即使调用了Activity的finish()方法,Activity对象还是一直没法被虚拟机正常回收。

解决的方法也很简单,我们可以传入一个Applicaton替换传入的其它需要被及时回收的Context对象。


  • 使用属性动画也可能导致内存泄漏的发生

属性动画的内存泄漏很像Handler的内存泄漏,属性动画在未执行完成前会持有相应执行动画View的引用,此时即使进行finish()可能就会出现Activity无法回收的情况发生。

解决的方法呢就是在Activity的onDestory()方法中执行属性动画的cancel()方法,释放引用的View对象。


  • 静态的Map和List导致的内存泄漏

及时的移除不再使用的集合对象。



相关的开源库与工具


  • LeakCanary


  • MAT



ANR出现的原因与调查方法

ANR之后会将相关的anr文件保存到data/anr/traces.txt下。



相关的开源库与工具


  • Hugo

通过@DebugLog注解,可以使用在Class或者Method域上,通过Aspectj进行代码注入,可以打印出输入与输出和Method执行的时间。


  • BlockCanary

这种进行UI主线程耗时的监听方式真的很巧妙,不得不佩服作者思维的灵活。

熟悉Looper源码的可以知道,Looper的

loop()

方法在调用

dispatchMessage()

前后会分别调用通过

Looper.getMainLooper().setMessageLogging()

传入的Print对象的

println()

方法,这时我们就能够利用这个方法统计

dispatchMessage()

执行消耗的事件,与其它很多有用的信息。


原理:


BlockCanary — 轻松找出Android App界面卡顿元凶


  • Android Profiler


AndroidStudio3.0 Android Profiler分析器



布局优化

当一个项目的界面变得越来越复杂之后,界面布局的层级可能会变得非常的多,这时界面的measure、layout和绘制就可能会非常的耗时。因此我们可以从布局层级来进行优化。


  • layout

    标签


  • ViewStub

    标签


  • Merge

    标签:

  • ConstraintLayout:

  • RecyclerView的Adapter中ViewHolder可以使用纯代码替代xml文件提高创建速度



相关的开源库与工具

  • HierarchyViewer (新版本已经被移除)
  • Layout inspector



界面启动优化

  • Application的onCreate()方法中减少方法调用,第三方库的初始化需要按照优先级别进行分类,非必须的进行延后加载。
  • 界面的初始化例如Fragment的懒加载

    setUserVisibleHint()
  • 修改启动时的Theme,提高用户体验
  • 界面的绘制尽量采用懒加载的机制,减少启动界面时界面绘制消耗的时间



APK大小的优化

  • shrinkresouce
  • .so文件过滤掉不常见的cpu架构,如:x86
  • 优化图片的格式,在对图片质量要求不高的情况下,使用有损压缩的格式。
  • 使用svg形式的图片显示
  • proguard 进行代码混淆



网络请求优化

网络请求优化的点主要在请求速度与流量消耗两方面:

  • 压缩通信时的JSON文本,可以采用GZIP压缩传输的数据。

  • 接口设计时携带更多有用信息,删除无用的字段,优化业务逻辑,合并接口。

  • 图片请求使用合适的缓存策略:

    1. 内存缓存LruCache。
    2. 磁盘缓存DiskLruCache。
  • 设计合适的缓存策略,思考哪些内容可能短时间不会发生改变,或者即使发生了变化用户从体感上也不会有所察觉,比如说

  • 使用GSON流式解析。



电量优化

  1. 推送与通知除非是非常有必要的情况下,比如说“收到钱”这类的重要事情,其它情况下尽量不要唤醒应用。
  2. 减少网络请求的次数。
  3. 如果需要定位时,如果不需要特别精确的坐标的话,可以使用Wifi或者移动网络进行定位。

例如:

电台应用可能是需要判断当前是哪个城市即可,然后根据城市判断显示哪些频道可以显示出来。



版权声明:本文为z2wenfa原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。