较好的相关文章:
https://blog.csdn.net/qq_30993595/article/details/80277333
https://blog.csdn.net/anwanfei/article/details/81140013
https://blog.csdn.net/WHB20081815/article/details/70245594
ANR错误定义(主线程才会导致ANR)
1.用户进行按键操作或者触屏操作时候,应用程序在默认时间范围内(5s)未及时处理,就会出现ANR,其实别说5s了,就是超过1s,用户都觉得不可接受,这种ANR的检测是system_server进程的Inputdispatcher不断检测是否处理完用户的输入事件,一旦超时,就会出现ANR了。
2.主线程在执行broadcastReceiver的onReceiver回调方法在10s内没有处理完事件
3.主线程在执行Service的各个生命周期函数中超过20s没有处理结束
4.大量的线程死循环的去做任务,导致应用获取不到CPU的时间片去处理用户输入事件
ANR错误出现原因:
只有当应用程序的UI线程响应超时才会引起ANR 超时产生的原因包括:
①当前事件没有机会处理,例如UI线程正在响应另外的事件,当前事件被某个事件给阻塞掉了;
②当前事件正在处理 但是由于耗时太长没有能及时的完成。其他原因:
③在BroadcastReceiver里做耗时的操作或计算;
④CPU使用过高;
⑤发生了死锁;
⑥耗时操作的动画需要大量的计算工作,可能导致CPU负载过重。
这六种情况其实总结成两个根本原因:
1.主线程做了耗时操作,导致后续用户的输入事件没有及时处理,这是谷歌不可接受的,这样极大的影响用户的体验,只能给开发者抛出来,你得必须给我解决。
2.我们知道应用的事件,不管进程还是线程,最终都是要获取CPU的时间片去处理,假如CPU负载过大,达到100%了,并且还有不断的新事件进入队列,那新事件只能等待了,假如这个新事件是用户的输入事件,那又回到原因1了,但是又有不同,因为这个新的事件可能并不是一个耗时事件;但是在规定的时间内,nputdispatcher检测到这个新事件没有处理完,那也会抛出ANR,让开发者去解决CPU负载问题。
原因如此,那平时开发如何避免呢
1.主线程中不要做任何耗时操作,将这些放到子线程去做
2.开发中注意线程的使用,有没有导致CPU负载过高
ANR错误定位
如果开发机器上出现ANR问题时,系统会生成一个traces.txt的文件放在/data/anr下,最新的ANR信息在最开始部分
如何去分析ANR呢:
各个进程的CPU使用情况;
CPU负载;
IOWait;
traces文件;
遇到ANR(Application Not Responding)是比较常见的问题。一般情况下,果ANR发生,对应的应用会收到SIGQUIT异常终止信号,dalvik虚拟机就会自动在/data/anr/目录下生成trace.txt文件,这个文件记录了在发生ANR时刻系统各个线程的执行状态,获取这个文件是不需要root权限的,因此首先需要做的就是通过adb pull命令将这个文件导出并等待分析。产生ANR的原因有很多,比如CPU使用过高、事件没有得到及时的响应、死锁等。
辅助处理ANR问题的工具
Traceview - 系统性能分析工具,用于定位应用代码中的耗时操作
Systrace - Android4.1新增的应用性能数据采样和分析工具
2.Android多进程是什么、如何定义、好处、以及可能出现的问题?原书第36页相关文章:
https://blog.csdn.net/lixpjita39/article/details/77435156
https://blog.csdn.net/goodlixueyong/article/details/49853079
2.1 为何要使用多进程
1.分散内存的占用
我们知道Android系统对每个应用进程的内存占用是有限制的,而且占用内存越大的进程,通常被系统杀死的可能性越大。让一个组件运行在单独的进程中,可以减少主进程所占用的内存,避免OOM问题,降低被系统杀死的概率,
2.实现多模块
比如我做的应用大而全,里面肯定会有很多模块,假如有地图模块、大图浏览、自定义WebView等等(这些都是吃内存大户),还会有一些诸如下载服务,监控服务等等,一个成熟的应用一定是多模块化的。
3.子进程奔溃,主进程可以继续工作
如果子进程因为某种原因崩溃了,不会直接导致主程序的崩溃,可以降低我们程序的崩溃率。 4.主进程退出,子进程可以继续工作
即使主进程退出了,我们的子进程仍然可以继续工作,假设子进程是推送服务,在主进程退出的情况下,仍然能够保证用户可以收到推送消息。
5.实现守护进程
2.2 多进程的创建
process分私有进程和全局进程:
私有进程的名称前面有冒号:android:process=":musicservice"
全局进程的名称前面没有冒号:android:process="com.trampcr.musicdemo.service"
2.3 使用多进程带来的麻烦
1)Application的多次重建。
2)静态成员和单例模式的完全失效。
3)文件共享问题。--Sharedpreference的可靠性下降
4)断点调试问题等
3.序列化与反序列化--原书第42页1、序列化是干什么的?
简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
2、什么情况下需要序列化
a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; b)当你想用套接字在网络上传送对象的时候; c)当你想通过RMI传输对象的时候;
3、Parcelable和Serializable的区别:
内存间数据传输时推荐使用Parcelable,如activity间传输数据
保存到本地或者网络传输时推荐使用Serializable
4.binder相关--原书第47页参考博客:Android AIDL跨进程通信
https://blog.csdn.net/cpcpcp123/article/details/90208023
这个讲解IPC例子很好的一个文章:https://github.com/leavesC/IPCSamples