没错, 这就是 Android 开发童鞋需要了解的 Generational Heap Memory 模型, 这里我们只关心当对象在 Young Generation 中存活了一段时间之后, 如果没被干掉, 那么会被移动到 Old Generation 中, 同理, 最后会移动到 Permanent Generation 中. 那么用脚想一想就知道, 如果内存泄露了, 那么, 抱歉, 你那块内存随时间推移自然而然将进入 Permanent Generation 中, 然鹅, 内存不是白菜, 想要多少就有多少, 这里, 因为沙盒机制的原因, 分配给你应用的内存当然是有那么一个极限值的, 你不能逾越 (有人笑了, 不是有 large heap 么, 当然我也笑了, 我并没有看到这货被宗师 android 玩家青睐过), 好了, 你那块造成泄露内存的对象占着茅坑不拉屎, 剩下来可以供其他对象发挥的内存空间就少了; 打个比方, 舞台小了, 演员要登台表演, 没有多余空间, 他就只能等待其他演员下来他才能表演啊, 这等待的时间, 是没法连续表演的, 所以就卡了嘛.
2, 频繁 GC
呵呵, 频繁 GC 会造成卡顿, 想必你经过上面的洗礼, 已经知道了为什么, 不错, 当然也是因为 "舞台空间不足, 新的演员上台表演需要先让表演完的下来". 那么造成这种现象的原因是什么呢?
a, 内存泄露, 好的, 你懂了, 不用讲了, 这个必须有可能会造成.
b, 大量对象短时间被创建, 又在短时间内 "需要" 被释放, 注意这里的需要, 其实是不得不, 为什么, 同样是因为 "舞台空间不够了", 举个例子, 在 onDraw 中 new 对象, 因为 onDraw 大约 16ms 会执行一次 (wait, 你能否确定一下, 什么是大约 16ms, 对不起, 不能, 掉帧了就不是, 哪怕掉那么一点点). 脑补一下, 每秒中创建大约 60 个对象, 嗯, 骚年, 你以为 Young Generation 是白菜么, 想拿多少就拿多少, 对不起, 这里是限量的, 这里用完了, 在来申请, 我就得去回收一些回来, 我回收总得耗时间吧, 耗时间, 好吧, onDraw 等着等着就错过了下一个 16ms 的执行了, 如是, 用户看起来就卡了.
3, 耗电问题
km 上有一个问题很尖锐, 说是微视看小视频看一会手机就会发烫, 所以, 用户一直就很关注耗电问题, 不过不好意思, 我们的 app 至今还没有遇到过严重的耗电问题, 虽然没有遇到比较严重的耗电问题, 不代表就不需要去了解这样的问题的解决办法, 我总结有:
a, 没有什么特别重要的信息, 比如, 钱到账, 电话来了, 100 元实打实无门槛代金券方法, 等等, 请不要打扰用户, 不要频繁唤醒用户, 否则, 结果只能是卸载, 或者关闭一切通知.
b, 适当的做本地缓存, 避免频繁请求网络数据, 这里, 说起来容易, 做起来并非三刀两斧就能搞定, 要配合良好的缓存策略, 区分哪些是一段时间不会变更的, 哪些是绝对不能缓存的很重要.
c, 对某些执行时间较长的同步操作在用户充电且有 wifi 的时候在做, 除非用户强制同步.. 等等, 就不扯太多, 因为后面还有很多内容.
4,OOM 问题
呵呵, 这个问题, 想必经过前面 1,2 的洗礼, 你应该已经明白这个什么原因导致的, 你可以想想一下 "舞台上将要上的一个演员是一个巨大胖子, 即便不表演的演员都下来了, 他还是挤不上去, 怎么办, 演砸了, 还能怎么办, 直接崩溃, 散场!" 造成这个问题的原因, 可能有,(呵呵, 保险起见, 只能说可能, 分析的时候可以从这里出发)
a, 内存泄露了, 想必你会心一笑.
b, 大量不可见的对象占据内存, 这个其实, 很常见, 只是大家可能一直不太关心罢了, 比如, 请求接口返回了列表有 100 项数据, 每项数据比如有 100 个字段, 其中你用户展示数据的只有 10 几个而已, 但是, 你解析的时候, 剩下的 99 个不知不觉吃了你的内存, 当, 有个胖子要内存时, 呵呵, 嗝屁了.
c, 还有一种很常见的场景是一个页面多图的场景, 明明每个图只需要加载一个 100*100 的, 你却使用原始尺寸 (1080*1980)or 更大, 而且你一下子还加载个几十张, 扛得住么? 所以了解一下 inSampleSize, 或者, 如果图片归你们上传管理, 你可以借助万象优图, 他为你做了剪切好不同尺寸的图片, 这样省得你在客户端做图片缩放了.
来源: https://juejin.im/post/5b194563e51d4506d25e20f5