深入理解handler机制
来源:互联网 发布:android 网络请求mvp 编辑:程序博客网 时间:2024/05/18 14:14
- 在Android 中handler的基本用法
import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;public class MainActivity extends AppCompatActivity { //主线程中的handler private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { } }; //子线程中执行 private Thread mTask = new Thread(new Runnable() { @Override public void run() { try { //执行任务需要2秒 Thread.sleep(2000); //操作UI Message msg = new Message(); Message mm = Message.obtain(); mHandler.sendMessage(msg); } catch (InterruptedException e) { e.printStackTrace(); } } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); downloadPicture(); } private void downloadPicture() { mTask.start(); }}
使用handler的基本原理
(1)利用handler.sendMessage()把子线程需要携带的数据发送到MessageQueue消息队列中,与消息队列绑定的取消息的Looper,轮询的从MessageQueue中取出消息,交给handler,分发并处理消息。
(2)默认情况下,在主线程实例化handler,默认情况下,在应用启动时,主线程的Looper和MessageQueue已经被创建。
(3)handler和looper的对应关系
多个handler可以对应一个looper。looper从messageQueue中取出不同的消息,根据msg.target传送给不同的handler进行处理。
(4)主线程Looper.loop()方法时,如果没有消息,则处于等待状态,如果有消息则发送给handler。
当没有消息时,linux系统是如何处理的?
linux系统的管道通讯,当读的一端没有读到内容则会休眠,而当写的一端写入内容时则会唤醒读的一端,利用这样的原理实现了Looper.loop()无限轮询读取消息而不会卡死。查看android源码来深入理解
(1)android应用启动时,首先调用ActivityThread类的main()方法如下
public static void main(String[] args){ ... Looper.prepareMainLooper(); //初始化Looper ... ActivityThread thread = new ActivityThread(); //实例化一个ActivityThread thread.attach(false); //这个方法最后就是为了发送出创建Application的消息 ... Looper.loop(); //主线程进入无限循环状态,等待接收消息}
接下来看一下Looper.prepareMainLooper()方法做了什么事情?
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } //拿到主线程的mainLooper sMainLooper = myLooper(); } }
其中prepare()方法,相当于Looper构造方法。
private Looper(boolean quitAllowed) { //在Looper构造方法中,初始化MessageQueue对象 mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
然后Looper.loop()方法
public static void loop() { // 拿到主线程的looper final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } //拿到主线程looper所对应的messageQueue消息队列 final MessageQueue queue = me.mQueue; ... //进入死循环,无限轮询的从消息队列中取出消息 for (;;) { Message msg = queue.next(); // might block if (msg == null) { return; } ... //如果有消息则会执行msg.target即对应handler的dispatchMessage(msg)方法,进而执行handleMessage()方法。 try { msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } }
再从事件发起者handler入手,当handler.sendMessage()时是如何执行的?
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { // 首先拿到消息队列messageQueue MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); }
然后执行enqueueMessage(queue, msg, uptimeMillis)方法如下
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { // 把当前的handler对象赋值给msg.target作为标记。 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } //把消息放入到消息队列中。 return queue.enqueueMessage(msg, uptimeMillis); }
4 总结:
(1)在主线程中,调用Looper.prepare()方法,创建主线程的Looper对象及消息队列MessageQueue
(2)在子线程中,handler.sendMessage()方法,将handler赋值给message对象作为标记,并把消息放入到消息队列中去
(3)在主线程中,Looper.loop()方法执行,轮询从消息队列中取出消息,如果没有则等待休眠,如果有则交给message指定的handler处理消息。
截此为止,完成了一个主线程和子线程通信的过程。也即handler的核心机制,线程通信的核心模块。
用一张图表示如下:
- 根据handler机制,实现从主线程向子线程发消息
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 在主线程中,把消息的msg.target赋值给handler,并把消息放在消息队列中。 mHandler.sendMessage(Message.obtain()); }
//子线程中的handler private Handler mHandler; //子线程中执行 private Thread mTask = new Thread(new Runnable() { @Override public void run() { Looper.prepare(); // 此处生成Looper对象及MessageQueue消息队列 // handler拿到消息调用分发消息和处理消息 mHandler = new Handler() { @Override public void handleMessage(Message msg) { //此处可以在子线程中操作toast,因为show()方法,进行了post,相对于在主线程中操作了,所以此处会弹出吐司。 Toast.makeText(MainActivity.this,"我是子线程的吐司",Toast.LENGTH_SHORT).show(); } }; Looper.loop(); //在子线程中Looper不停了从消息队列中取消息,发给对应的handler进行处理 } });
@Override protected void onDestroy() { //当界面退出时,把子线程任务清除掉 mHandler.removeCallbacksAndMessages(null); super.onDestroy(); }
- 深入理解Handler机制
- 深入理解handler机制
- 深入源码理解Handler机制
- 深入理解android Handler机制
- 深入理解Handler消息传递机制详解
- 【Android 学习】深入理解Handler机制
- 深入理解Android中的Handler机制
- 带你深入理解Android Handler机制
- 带你深入理解Android Handler机制
- 深入理解Android中Handler机制
- 深入理解Android中的Handler机制
- 深入理解Android Handler 消息机制
- Handler 机制深入理解(Handler、Looper、MessageQueue)
- activity的深入浅出-------通过几个问题来深入理解handler机制
- Handler,Looper,Message,MessageQueue,Thread机制的深入理解(举例说明)
- 深入理解异步消息处理机制Message,handler,MessageQueue,looper
- Android消息机制——深入理解Handler
- Android 异步消息处理机制 深入理解 Looper、Handler、Message
- spring和mybatis整合
- 初识AngularJS
- VS2010+QT4.8静态编译过程讲解。
- 人工智能和机器学习如何颠覆零售行业?
- LabVIEW 线程池的理解
- 深入理解handler机制
- POJ1201 Intervals
- Centos7安装并配置mysql5.6完美教程
- App图标不显示:Xcode项目在Xcode9中运行会出现AppIcon不显示的 BUG
- 第一篇
- AndroidStudio 版本管理设置忽略文件
- Matisse 与 Glide -- java.lang.NoSuchMethodError: com.bumptech.glide.RequestManager.load
- WEB安全测试的类型
- Robot in Maze----BFS