文章插图
1.OOM和崩溃优化1.1 ANR优化
ANR的产生需要满足三个条件主线程:只有应用程序进程的主线程响应超时才会产生ANR;超时时间:产生ANR的上下文不同 , 超时时间也会不同 , 但只要在这个时间上限内没有响应就会ANR;输入事件/特定操作:输入事件是指按键、触屏等设备输入事件 , 特定操作是指BroadcastReceiver和Service的生命周期中的各个函数 , 产生ANR的上下文不同 , 导致ANR的原因也会不同;ANR优化具体措施将所有耗时操作 , 比如访问网络 , Socket通信 , 查询大量SQL 语句 , 复杂逻辑计算等都放在子线程中去 , 然 后通过handler.sendMessage、runonUIThread、AsyncTask 等方式更新UI 。无论如何都要确保用户界面作的流畅 度 。如果耗时操作需要让用户等待 , 那么可以在界面上显示度条 。使用AsyncTask处理耗时IO操作 。在一些同步的操作主线程有可能被锁 , 需要等待其他线程释放相应锁才能继续执行 , 这样会有一定的ANR风险 , 对于这种情况有时也可以用异步线程来执行相应的逻辑 。另外 , 要避免死锁的发生 。使用Handler处理工作线程结果 , 而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程 。Activity的onCreate和onResume回调中尽量避免耗时的代码BroadcastReceiver中onReceive代码也要尽量减少耗时 , 建议使用IntentService处理 。各个组件的生命周期函数都不应该有太耗时的操作 , 即使对于后台Service或者ContentProvider来讲 , 应用在后台运行时候其onCreate()时候不会有用户输入引起事件无响应ANR , 但其执行时间过长也会引起Service的ANR和ContentProvider的ANR
2.内存泄漏优化内存检测第一种:代码方式获取内存/** * 内存使用检测:可以调用系统的getMemoryInfo()来获取当前内存的使用情况 */private void initMemoryInfo() { ActivityManager activityManager = (ActivityManager) Utils.getApp() .getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); if (activityManager != null) { activityManager.getMemoryInfo(memoryInfo); LogUtils.d("totalMem=" + memoryInfo.totalMem + ",availMem=" + memoryInfo.availMem); if (!memoryInfo.lowMemory) { // 运行在低内存环境 } }}内存检测第二种:leakcanary工具LeakCanary的原理是监控每个activity , 在activity ondestory后 , 在后台线程检测引用 , 然后过一段时间进行gc , gc后如果引用还在 , 那么dump出内存堆栈 , 并解析进行可视化显示 。
2.0 动画资源未释放
问题代码
public class LeakActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_leak); textView = (TextView)findViewById(R.id.text_view); ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(textView,"rotation",0,360); objectAnimator.setRepeatCount(ValueAnimator.INFINITE); objectAnimator.start(); }}解决办法
@Overrideprotected void onDestroy() { super.onDestroy(); mAnimator.cancel();}在属性动画中有一类无限循环动画 , 如果在Activity中播放这类动画并且在onDestroy中去停止动画 , 那么这个动画将会一直播放下去 , 这时候Activity会被View所持有 , 从而导致Activity无法被释放 。解决此类问题则是需要早Activity中onDestroy去去调用objectAnimator.cancel()来停止动画 。
2.1 错误使用单利
在开发中单例经常需要持有Context对象 , 如果持有的Context对象生命周期与单例生命周期更短时 , 或导致Context无法被释放回收 , 则有可能造成内存泄漏 。比如:在一个Activity中调用的 , 然后关闭该Activity则会出现内存泄漏 。解决办法:要保证Context和AppLication的生命周期一样 , 修改后代码如下:this.mContext = context.getApplicationContext();1、如果此时传入的是 Application 的 Context , 因为 Application 的生命周期就是整个应用的生命周期 , 所以这将没有任何问题 。2、如果此时传入的是 Activity 的 Context , 当这个 Context 所对应的 Activity 退出时 , 由于该 Context 的引用被单例对象所持有 , 其生命周期等于整个应用程序的生命周期 , 所以当前 Activity 退出时它的内存并不会被回收 , 这就造成泄漏了 。
推荐阅读
- 探索 Android 内存优化方法
- MySQL:常用的30种SQL查询语句优化方法
- 2019年seo动态网页优化“指南针”
- 微信小程序页面传值、组件间通信总结
- 资深架构师总结:彻底搞懂NIO效率高的原理
- 老司机总结雨刮器功能,除了刮玻璃,还有这4个,你知道几个?
- SEO优化和SEM对比的优势体现
- 中继器、集线器、网桥、交换机、路由器、网关的超全总结
- 网友总结户外知识:疲劳防护和体能恢复
- 各种排序算法总结