Android的异步消息处理机制笔记
2017-05-11 14:50
381 查看
标签(空格分隔): 未分类
研究了一下安卓的异步消息处理机制,做下笔记。
首先,我是先看了郭霖的文章–Android异步消息处理机制完全解析,带你从源码的角度彻底理解
处理流程:
看完后总结了一下:
1. 在主线程中可以直接创建Handler对象,而在子线程中需要先调用Looper.prepare()才能创建Handler对象。
2. 在主线程中更新UI的原理就是handlerMessage()方法是运行在Handler所绑定的Looper所在的线程。
new Thread(new Runnable() { @Override public void run() { handler = new Handler(getMainLooper()){ @Override public void handleMessage(Message msg) { //此时handleMessage运行在UI线程中 Log.e("lzz",Thread.currentThread().getName()); } }; handler.sendEmptyMessage(0); } }).start();
new Thread(new Runnable() { @Override public void run() { Looper.prepare(); handler = new Handler(){ @Override public void handleMessage(Message msg) { //此时handleMessage运行在子线程中 Log.e("lzz",Thread.currentThread().getName()); } }; handler.sendEmptyMessage(0); Looper.loop(); } }).start();
3. 关于Looper.loop()的理解。
Looper.loop()方法会开启一个死循环来迭代队列里的消息,如果上述子线程中创建Handler的代码改成这样Looper.loop();// 这里是一个死循环 // 此后的代码无法执行 handler.sendEmptyMessage(0);
那么为什么主线程中的Looper.loop()一直无限循环为什么不会造成ANR呢?
参考了以下内容来理解
转:
正如我们所知,在Android中如果主线程中进行耗时操作会引发ANR(Application Not Responding)异常。
造成ANR的原因一般有两种: 当前的事件没有机会得到处理(即主线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了) 当前的事件正在处理,但没有及时完成
为了避免ANR异常,android使用了Handler消息处理机制。让耗时操作在子线程运行。
因此产生了一个问题,主线程中的Looper.loop()一直无限循环检测消息队列中是否有新消息为什么不会造成ANR?
源码分析
ActivityThread.Java 是主线程入口的类,这里你可以看到写Java程序中司空见惯的main方法,而main方法正是整个Java程序的入口。
ActivityThread源码 public static final void main(String[] args) { ... //创建Looper和MessageQueue Looper.prepareMainLooper(); ... //轮询器开始轮询 Looper.loop(); ... } Looper.loop()方法 while (true) { //取出消息队列的消息,可能会阻塞 Message msg = queue.next(); // might block ... //解析消息,分发消息 msg.target.dispatchMessage(msg); ... }
显而易见的,如果main方法中没有looper进行循环,那么主线程一运行完毕就会退出。这还玩个蛋啊!
总结:ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了。
我们知道了消息循环的必要性,那为什么这个死循环不会造成ANR异常呢?
因为Android 的是由事件驱动的,looper.loop() 不断地接收事件、处理事件,每一个点击触摸或者说Activity的生命周期都是运行在 Looper.loop() 的控制之下,如果它停止了,应用也就停止了。只能是某一个消息或者说对消息的处理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。
也就说我们的代码其实就是在这个循环里面去执行的,当然不会阻塞了。
handleMessage方法部分源码 public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case LAUNCH_ACTIVITY: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); final ActivityClientRecord r = (ActivityClientRecord) msg.obj; r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo); handleLaunchActivity(r, null); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; case RELAUNCH_ACTIVITY: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart"); ActivityClientRecord r = (ActivityClientRecord) msg.obj; handleRelaunchActivity(r); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; case PAUSE_ACTIVITY: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); handlePauseActivity((IBinder) msg.obj, false, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 2) != 0); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case PAUSE_ACTIVITY_FINISHING: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); handlePauseActivity((IBinder) msg.obj, true, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 1) != 0); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; ........... } }
可以看见Activity的生命周期都是依靠主线程的Looper.loop,当收到不同Message时则采用相应措施。
如果某个消息处理时间过长,比如你在onCreate(),onResume()里面处理耗时操作,那么下一次的消息比如用户的点击事件不能处理了,整个循环就会产生卡顿,时间一长就成了ANR。
让我们再看一遍造成ANR的原因,你可能就懂了。
造成ANR的原因一般有两种: 当前的事件没有机会得到处理(即主线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了) 当前的事件正在处理,但没有及时完成
而且主线程Looper从消息队列读取消息,当读完所有消息时,主线程阻塞。子线程往消息队列发送消息,并且往管道文件写数据,主线程即被唤醒,从管道文件读取数据,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。因此loop的循环并不会对CPU性能有过多的消耗。
总结:Looer.loop()方法可能会引起主线程的阻塞,但只要它的消息循环没有被阻塞,能一直处理事件就不会产生ANR异常。
以上。
相关文章推荐
- Android笔记----AsyncTask异步消息处理机制
- Android异步消息处理机制总结笔记
- Android异步消息处理机制学习笔记
- 《第一行代码》自学笔记-Android中异步消息处理机制&&AsyncTask的用法
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- Android多线程及异步任务消息处理机制(一)--Handler的使用
- 【转】Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- Android多线程----异步消息处理机制之Handler详解
- Android Handler 异步消息处理机制的妙用 创建强大的图片加载类
- android异步消息处理机制
- Android消息处理机制笔记
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android消息处理机制(Looper,Handler,MessageQueue笔记)
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解(Handler+Message处理机制)
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- android的异步消息处理机制
- [学习总结]6、Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- Android Handler 异步消息处理机制的妙用 创建强大的图片加载类