深入理解handler机制

来源:互联网 发布:android 网络请求mvp 编辑:程序博客网 时间:2024/05/18 14:14
  1. 在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();    }}
  1. 使用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()无限轮询读取消息而不会卡死。

  2. 查看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的核心机制,线程通信的核心模块。
用一张图表示如下:

这里写图片描述

  1. 根据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();    }
原创粉丝点击