#Android 消息机制handler详细攻略+源码解析
Android 消息机制handler快速攻略,相信读者开发中都遇到过,Android建议不要在主线程中进行耗时操作,否则会导致程序无法响应即ANR.还有网络访问,我们需要从服务端拉取一些信息并将其显示在UI上,这个时候必须在子线程中进行拉取工作,获取数据完毕后又不能在子线程中直接访问UI,如果没有Handler,那么我们的确没有办法将访问的UI工作切换到主线程中去执行.因此,系统之所以提供Handler,主要原因就是为了解决在子线程中无法访问UI的矛盾.在这之前我们需要了解下面几个知识点
安卓线程安全问题: 如果多个线程并发的操作UI组件,是可能导致线程的安全问题出现(如果加上锁机制,2缺点:一逻辑复杂化,二锁机制降低UI访问效率)
解决线程安全: 安卓提供解决的机制,只允许在UI主线程做组件修改
什么是UI主线程: 应用第一次启动时,系统默认启动一条UI线程(也称之为:主线程),专门负责处理UI相关的event
怎么在新线程修改UI组件: 这时候就需要使用Android中提供的一种异步回调机制Handler
消息队列在Android中指的是MessageQueue,MessageQueue主要包含两个操作:插入和读取.读取操作本很会伴随着删除操作,插入和读取对应的方法分别为恩enqueueMessage和next,其中enqueueMessage的作用是往消息队列中插入一条消息,而next的作用是从消息队列中取出一条消息并将其从消息队列中移除.尽管MessageQueue叫消息队列,但是它的内部实现并不是用的队列,实际上它是通过一个单链表的数据结构来维护消息列表,单链表在插入和删除上比较有优势.
下面主要看一下它的enqueueMessage和next方法的实现
enqueueMessage的实现来看,他的主要才做其实就是单链表的插入操作.
下面是next主要逻辑如下所示
可以发现next方法是一个无限循环的方法,如果消息队列中没有消息,那么next方法会一直阻塞在这里.当有新消息到来时,next方法会返回这条消息并将其从单链表中移除.
Looper在Android的消息机制中扮演着消息循环的角色,它会不停地从MessageQueue中查看是否有新消息,如果有新消息就会立刻处理,否则就一直阻塞在那里.它的构造方法,会创建一个MessageQueue即消息队列,然后将当期线程的对象保存起来
其次,通过Looper.prepare()即可为当前线程创建一个Looper,接着通过Looper.loop()来开启消息循环
Looper的loop方法的工作过程比较好理解,loop方法是一个死循环,唯一跳出循环的方式是MessageQueue的next方法返回了null.当Looper的quit方法被调用时,Looper就会调用MessageQueue的quite或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,它的next方法就会返回null.也就是说,Looper必须退出,否则loop方法就会无限循环下去.
Handler的工作主要包含消息的发送和接收过程.消息的发送可以通过post的系列方法以及send的系列方法来实现,post的系列方法最终是通过sed的一系列方法来实现的.
从上面可以发现,Handler发送消息的过程仅仅是向消息队列中插入了一条消息,MessageQueue的next方法就会返回这条消息给Looper,Looper收到消息后就开始处理了,最终消息由Looper交由Handler处理,即Handler的diapatchMessage方法会被调用,这是Handler就进入了处理消息的阶段
Handler处理消息的过程可以归纳为一个流程图.
这个ThreadLocal相信不少读者很少接触到,日常开发汇总用到ThreadLocal的地方较少,ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储后,只有在指定线程中获取到存储的数据,对于其他线程来说则无法获取到数据.但是在某些特殊的场景下,通过ThreadLocal可以轻松地实现一些看起来很复杂的功能,在Android的源码种有所体现,比如Looper,ActivityThread以及AMS中都用到了ThreadLocal.
上线项目用到地方举例:
1,在一个教育学习项目中,作业的定时上报成绩,把内存缓存中的学生成绩上报
2,VR教学中控项目,实时刷新补抓VR状态
核心代码部分:
public void init(){
//开始刷状态数据
mHandler.post(runnable);
}
//5秒
Runnable runnable = new Runnable() {
@Override
public void run() {
mHandler.postDelayed(runnable, 10 * 1000);
Message message = new Message();
message.what = 1;
mHandler.sendMessage(message);
}
};
public Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
//todo
break;
}
}
};
//用完回收
@Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(runnable);
}
为自己技术增值,量变引起质变.对象亦来源于生活,模式亦来源于验证的OO经验,那么请学会使用轮子,再到感受制造轮子的乐趣,你会发现原来编程那么美妙.如有错误或不当之处,请读者留言,博主好吸取经验,互相交流学习,如果本文对你有帮助请帮博主点赞,发注一波,谢谢善良的读者