模拟实现Android的Handler

一、前言

        在Android应用的开发中,Handler的使用是必不可少的,包括目前的面试也都比较喜欢问这一类的问题,所以感觉我们现在不了解Handler都不好意思开口说做Android应用开发的了。抱着最近一段时间对Handler源码的了解,决定通过模拟Handler的实现,来表达和记录下我对Handler内部关系和消息发送之间的简化关系。

二、Handler的实现关系

       在查看Handler源码的过程中,通过抽丝剥茧的方式,我们可以看到实现Handler消息发送机制,主要组成有这几个类:Handler、Looper、MessageQueue、Message,  其之间的关系图如下:

图有点简陋,不过我们还是可以清晰了解到,它们采用了生产和消费的这种方式进行消息的分发,Handler通过sendMessage的方法把消息生产到MessageQueue的队列,Looper类里面有个对MessageQueue的 死循环,发现MessageQueue中有消息过来,就调用Message中持有的target,即Handler,进行dispatchMessage消息转发,从而完成了整个消息机制的闭环。(当然,这里是对源码的一个简化描述,真正的消息内容传过去还得从底层经过了IPC通信等一系列复杂的环节,不过这不影响我们借此来理解Handler

好了,接下来看我们的代码实现:

三、代码实现

1、Message.java类
public class Message {
    public int what;
    public int arg1;
    public int arg2;
    public Object obj;
    Handler target;
    Runnable callback;
    public Message(){
        
    }
}

2、MessageQueue.java类
public class MessageQueue {
    private final int MAX_SIZE = 10;
    /**阻塞的队列*/
    ArrayBlockingQueue<Message> queue = new ArrayBlockingQueue<Message>(MAX_SIZE);
    public void enqueueMessage(Message msg){
        try {
            queue.put(msg);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public Message next(){
        try {
            return queue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

3、Handler.java类
public class Handler {
    private Looper mLooper;
    private MessageQueue mQueue;
    /**
     * 使用默认无参构造函数创建Handler的时候,从我们查看
     * 源码知道,获取的是应用入口ActivityThread类的main函数中,调用了prepare方法所创建的Looper对象,
     * 这里获取到的就是主线程的Looper
     */
    public Handler(){
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
    }
    
    /**
     * 在这里传进了Looper对象,那就与创建该Looper所在的线程关联
     */
    public Handler(Looper looper){
        mLooper = looper;
        mQueue = mLooper.mQueue;
    }
    Callback mCallback;
    public final void sendMessage(Message msg){
        msg.target = this;
        mQueue.enqueueMessage(msg);
    }
    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }
    /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
    private static void handleCallback(Message message) {
        message.callback.run();
    }
    public interface Callback {
        public boolean handleMessage(Message msg);
    }
}

4、Looper.java类
public class Looper {

	/**多线程数据隔离*/
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();

    MessageQueue mQueue;

    private Looper(){
        mQueue = new MessageQueue();
    }

    public static void prepare(){
        if(sThreadLocal.get() != null){
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }

    /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static Looper myLooper() {
        return sThreadLocal.get();
    }

    public static void loop(){
        final Looper me = myLooper();
        if(me == null){
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            msg.target.dispatchMessage(msg);
        }
    }

}

5、测试类DemoTest.java,这里开启了10条线程来模拟不停给Handler发送消息,然后从Handler的回调handleMessage来进行回调打印显示。
public class DemoTest {
    public static void main(String[] args){
        Looper.prepare();
        final Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                System.out.println("handleMessage---->"+msg.obj.toString());
            }    
        };
        for(int i = 0 ; i < 10 ; i ++){
            new Thread(){
                @Override
                public void run() {
                    while(true){
                        Message msg = new Message();
                        msg.obj = "发送消息:"+Thread.currentThread().getName();
                        handler.sendMessage(msg);
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                
            }.start();
        }
        Looper.loop();
    }
}

6、打印结果
 

四、疑问回调
1、在测试类DemoTest中的main函数中,我们调用了Looper.loop(),不会发生死循环吗?
答:我想说,这本身就是程序的入口,好比源码里面的ActivityThread类的main函数,一旦跳出,那进程也就跟着结束了。

2、这样创建的Handler是在什么线程,UI主线程吗?
答:首先,这里只是一个普通的Java工程,没有UI主线程这一说法,其实Android里面的UI主线程也是相对来说的,在ActivityThread的被称为UI线程,这个之外的都被称为非UI子线程。那么在这里,我们的main里面创建的Handler就等于是一个主线程。

3、 那如何创建一个使用子线程Looper的Handler?
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //tv_show = (TextView)findViewById(R.id.tv_show);

    System.out.println("onCreate:"+Thread.currentThread().getName());

    new Thread(){
        @Override
        public void run() {
            System.out.println("run:"+Thread.currentThread().getName());
            Looper.prepare();
            Handler handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    System.out.println("handleMessage:"+Thread.currentThread().getName());
                }
            };
            handler.sendEmptyMessage(0);
            Looper.loop();
        }
    }.start();
    
}
打印的结果:
01-18 09:09:00.915 22009-22009/com.lsy.handerdemo I/System.out: onCreate:main
01-18 09:09:00.920 22009-22062/com.lsy.handerdemo I/System.out: run:Thread-221
01-18 09:09:00.925 22009-22062/com.lsy.handerdemo I/System.out: handleMessage:Thread-221
handleMessage处理的结果是在子线程的,这个时候我们创建的这个handler使用的是Looper.prepare()在子线程创建的Looper,所以在loop循环消息分发的时候,也在子线程里面进行回调。

五、总结
       当然Handler和Looper内部的实现不可能那么简单,还要比这复杂得多很多,不过通过这样的一个模拟过程,至少可以加深我们对Handler机制的了解,何尝不是一件好事呢。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值