美文网首页
Anroid App内存优化

Anroid App内存优化

作者: 北疆小兵 | 来源:发表于2019-12-17 18:20 被阅读0次

    背景

    在移动开发过程中,由于app内存和存储空间有限,而系统分配给每个app的内存是有一定限制的,当app申请的内存超过限制后,就有可能出现内存溢出而导致app崩溃,影响用户体验甚至导致用户卸载app,因此性能优化是非常值得投入的一个事情。一般来说,所有的优化都可以分为以下两种情况:

    *   以空间换时间(数据预加载)
    *   以时间换时间(1.串行改并行 2.懒加载:先初始化优先级高的,优先级低的延迟加载)
    

    定义

    优化处理 应用程序的内存使用、空间占

    作用

    避免因内存使用/管理不当,导致内存泄漏、 内存溢出、内存占用过大,导致app卡顿甚至崩溃

    常见的内存问题 & 解决方案

    • 常见的内存问题如下:
      内存泄露
      内存抖动
      图片Bitmap相关
      代码质量 & 数量
      日常不正确使用

    内存泄漏

    • 定义:在程序申请内存后,当该内存不再需要时,无法释放 & 归还给程序
    • 影响:当泄漏的内存达到一定程度,新申请的内存大于系统可分配内存时,则会造出内存溢出(OOM)
    • 发生内存泄漏的本质原因:生命周期长的对象持有生命周期短的对象
    • 常见内存泄漏
      集合类
      Static关键字修饰的成员变量
      非静态内部类 / 匿名类
      资源对象使用后未关闭

    图片资源Bitmap相关

    • 为什么需要优化bitmap:Android分配给每个应用的内存有限,而图片非常占用内存,很多情况下,图片所占内存占整个应用内存的大部分
    • 优化方向:
      • 使用完毕后释放资源:Bitmap.recycle, SoftWeafrence
      • 根据分辨率适配&缩放图片: 设置多套图片资源、BitmapFactory.decodeResouce、BitmapOption.inSampleSize
      • 按需选择合适的解码方式
      • 设置图片缓存: 1. 3级缓存 2.SoftReference

    内存抖动

    简介

    • 定义: 内存大小频繁上下较大范围波动
    • 原因:短时间内程序频繁创建对象 & 垃圾回收
    • 后果:频繁gc导致卡顿,甚至oom

    优化方案

    尽量避免频繁创建大量、临时的小对象

    常用性能优化tips

    • 线程池
      优先采用ThreadPollExecutor, 不要用new Thread(), 好处是

    1.线程可重复利用,节省线程的创建和回收开销
    2.控制线程的并发数,减少并发问题
    3.控制线程状态

    • UI
      1. 合理利用include、merge、viewstube,使用ConstraintLayout, 减少布局层级,提高页面渲染效率
      2. 窗口默认有一个不透明的背景,可以去掉的: getWindow().setBackground(null),或者修改xml
      3. ui局部刷新:用adatper.notifyItemChanged 替换adatper.notifyDataChanged()
      4. RecycleView替代ListView
    • Bitmap

    1.使用BitmapFactory.options 对图片压缩读取, inSampleSize:缩放比例,把图片载入内存之前,先计算合适的缩放比例。

    1. 对像素要求不高的情况下,Config由ARGB_8888改为 ARGB_565。
    2. 及时将bitmap置为null。
    3. 显示本地图片时,用tinypng压缩之后再使用
    4. 许多地方不需要存内存缓存,比如闪屏广告图,app启动之后就不会再使用了,可以加载的时候 memoryCache(false)
    5. 许多地方不需要磁盘缓存,比如发布动态,从图库中选图,不需要再存一份磁盘缓存了,本身那些图片都是本地图片。直接 diskCache(false)
    • 广播
      优先使用LocalBroadcastManger, 好处是:安全性,性能,运行效率更高

    • 在onActivity的onDestroy方法中,对资源和引用进行清除(例如imageview.setImageDrawable(null), editText.clearTextWatchers()),取消网络请求。

    • 耗时操作尽量使用Intentservice而不是service

    • 用SparseArray 替换key为int的HashMap 好处:SpaceArray更节省内存(SparseIntArray、SparseBooleanArray、SparseLongArray,可以支持存储<Integer,Integer>、<Integer,Boolean>、<Integer,Long>),HashMap对于key为int类型时,每次put值的时候会将int包装成Integer,涉及装箱

    • ObjectPool

      通过对象池技术达到重复利用,减少重复对象的创建

    • Job Schedule

      将不紧急的任务交给jobSchedule来处理,选择合适的时间,合适的网络,再一起进行

    • Anroid避免使用enum, 建议用annotation(参考View.setVisibility)

    • 使用StringBuffer或者StringBuilder,避免大量字符串的拼接

    • onLowMemory、onTrimMemory 释放资源

    • 使用Parceable代替Seriable传递序列化数据

    • 在性能敏感的代码中避免创建对象, 例如:onMeasure、onLayout、ondraw

    • WebView优化

      • WebView第一次创建比较耗时,可以预先创建WebView,提前将其内核初始化(webview首次初始化需200ms,第二次只需要20ms)
      • 使用WebView缓存池,用到WebView的地方都从缓存池取,缓存池中没有缓存再创建,注意内存泄漏问题
      • 本地预置html和css,WebView创建的时候先预加载本地html,之后通过js脚本填充内容部分
      • 提前从cdn中请求部分落地html。缓存到本地,点击详情时,只需从缓存中加载即可
      • WebView初始化完成,立刻loadUrl,无需等待框架onCreate或者OnResume结束
      • WebView初始完成后到页面首屏绘制完成之间,尽量减少UI线程的其他操作,繁忙的UI线程会拖慢WebView.loadUrl的速度
    • 启一个后台线程,定时去监控实时的内存使用情况,如果内存紧急了,直接清空Glide或者fresco的内存缓存

    启动优化

    • 通过AsyncLayoutInflater异步加载布局
    • 闪屏页优化
    • MultipDex优化(1.新启动一个进程去执行MultiDex优化,创建一个临时文件,作为判断MultiDex是否加载完的条件 2.启动LoadDexActivity去加载MultiDex(LoadDexActivity在单独进程,加载完会删除临时文件) 3.开启while循环,直到临时文件不存在跳出循环,进入Application的onCreate方法 )
    • 在Application的onCreate方法中预创建预创建SplashActivity和MainActivity
    • 数据预加载(对象第一次创建的时候,java虚拟机首先检查类对应的Class
      对象是否已经加载。如果没有加载,jvm会根据类名查找.class文件,将其Class对象载入。同一个类第二次new的时候就不需要加载类对象,而是直接实例化,创建时间就缩短了)
    • 第三方库懒加载(延迟 或者MessageQueue.addIdleHandler)
    • 线程优化
    • 系统调用优化

    避免内存泄漏

    • 优先使用Application 的Context而不是Activity Context
    • 内部类引用导致activity泄漏,尤其是Handler(采用静态内部类+弱引用解决)
    • Handler泄漏(弱饮用,onDestory中removeCallbacksAndMessages(null), 使用LifeCycleHandler)
    • 定时轮询任务
    • Cursor,Sqlite,File,IO等资源使用完记得关闭
    • 动画销毁的时候,停止动画
    • 各种监听器(例如广播接收者 ,EditText的addTextChangeListener)及时注销,静态集合及时清空

    定位性能问题

    • LeakCancary(继承displayLeakService,上报埋点)
    • BlockCancary 监听主线程耗时方法
    • 通过Aspect J等方式插桩(监控setContentView耗时,主线程耗时)
    • Systrace 和 函数插桩
    • TraceView
    • 替换looper的Printer(涉及到字符串拼接,推荐Debug模式下使用)
    • Profile
    • Mat

    相关文章

      网友评论

          本文标题:Anroid App内存优化

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