从零开始实现android的handler

Android 中handler 机制 概括起来需要三个步骤。

  1. Looper的准备工作,Looper.prepare()。
  2. 创建handler。
  3. Looper开始运作,Looper.loop()。

我们要从零开始实现handler 的机制,先从handler 要实现的功能开始。

Handler.java

package com.android;


public class Handler {
    final Looper mLooper;
    final MessageQueue mQueue;


    public Handler( ) {


        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                    "Can't create handler inside thread " + Thread.currentThread()
                            + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
    }





    public boolean sendMessage(Message msg ) {
        System.out.println("sendMessage");
        synchronized(mQueue) {

            msg.target = this;
            mQueue.add(msg);
            System.out.println("唤醒");
            mQueue.notifyAll();
        }
        return true;
    }

    public void handleMessage(Message msg) {
    }
    public void dispatchMessage(Message msg) {
        System.out.println("dispatchMessage");

            handleMessage(msg);

    }
}

 

Handler 需要实现 sendMessage 和 dispatchMessage , 即发送消息到 消息队列 和从消息队列取消息并处理, 典型的生产者和消费者模型。 只是这个消息队列属于当前线程。当前线程的消息队列 用mLooper.mqueue 来表示。 那么问题来了。 如果来实现当前线程的消息队列。

Looper.java

package com.android;

import java.lang.ThreadLocal;

public final class Looper {


    private static final String TAG = "Looper";

    static final ThreadLocal sThreadLocal = new ThreadLocal();

    final MessageQueue mQueue;


    private static Looper sMainLooper;  // guarded by Looper.class

    private Looper(boolean quitAllowed) {
        System.out.println("Looper 构造函数");

        mQueue = new MessageQueue( );

    }

    public static  Looper myLooper() {
        System.out.println("myLooper");

        return sThreadLocal.get();
    }

    public static void prepareMainLooper() {
            System.out.println("prepareMainLooper");
            prepare(false);
            synchronized (Looper.class) {
                if (sMainLooper != null) {
                    throw new IllegalStateException("The main Looper has already been prepared.");
                }
                sMainLooper = myLooper();
            }
    }

    private static void prepare(boolean quitAllowed) {
        System.out.println("prepare");

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

    public static void loop() {
            System.out.println("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;
            // Make sure the identity of this thread is that of the local process,
            // and keep track of what that identity token actually is.
            for (;;) {


                  synchronized(queue) {
                      while (queue.size() == 0) {
                          try {
                              System.out.println("wait here" );

                              queue.wait();
                          } catch (Exception e) {
                              System.out.println("wait error" + e.toString());

                          }
                      }
                      if (queue.size() > 0) {
                          System.out.println("处理消息"+ queue.size());
                          Message msg = queue.poll();
                          msg.target.dispatchMessage(msg);
                          System.out.println("处理完毕");
                      }
                  }
            }
    }
}

 

这里的Looper.prepare 就是将Looper和当前线程绑定。

Looper 是一个不断循环 从消息队列读消息并处理的生产者消费者模型。不断循环即由loop的for 循环驱动。 在消息队列没有消息时, 线程处于等待状态。当有消息入队时,通知线程处理 dispatchMessage。

Android 源码中的MessageQueue 实现方式 比较繁琐, 这里可以为了方便叙述和理解,直接使用java 的queue 。

MessageQueue.java

package com.android;

import java.util.*;

public class MessageQueue implements Queue {


    Queue  queue;

    MessageQueue(){
         System.out.println("MessageQueue 构造函数");
         queue = new LinkedList();
    }
    @Override
    public int size() {
        return  queue.size();
    }

    @Override
    public boolean isEmpty() {
        if( queue.size()==0){
            return  true;
        }else{
            return false;
        }
    }

    @Override
    public boolean contains(Object o) {
        return false;
    }

    @Override
    public Iterator iterator() {
        return null;
    }

    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @Override
    public Object[] toArray(Object[] objects) {
        return new Object[0];
    }

    @Override
    public boolean add(Object o) {
        System.out.println("add ");
        if( Message.class.isInstance(o)){
            queue.add((Message) o);
            System.out.println("current size "+queue.size());
            return true;
        }else{
            return false;
        }
    }

    @Override
    public boolean remove(Object o) {
        if( Message.class.isInstance(o)){
            queue.remove(o);
        }else{
            return false;
        }
        return true;
    }

    @Override
    public boolean addAll(Collection collection) {
        return false;
    }

    @Override
    public void clear() {
        queue.clear();
    }

    @Override
    public boolean retainAll(Collection collection) {
        return false;
    }

    @Override
    public boolean removeAll(Collection collection) {
        return false;
    }

    @Override
    public boolean containsAll(Collection collection) {
        return false;
    }

    @Override
    public boolean offer(Object o) {
        System.out.println("off ");
        if( Message.class.isInstance(o)){
            queue.offer((Message) o);

        }else{
            return  false;
        }
        return true;
    }

    @Override
    public Message remove() {
        Message msg = queue.remove();
        return msg;
    }

    @Override
    public Message poll() {
        System.out.println("poll ");
        Message msg = queue.poll();
        return msg;
    }

    @Override
    public Message element() {
        Message msg = queue.element();
        return msg;
    }

    @Override
    public Message peek() {
        System.out.println("peek ");
        Message msg = queue.peek();
        return msg;
    }
}

 

这里我们的MessageQueue 使用queue 接口类。

Message类这里只包含 target 和what 成员。

Message.java

package com.android;

public final class Message  {

    public int what;

    Handler target;

}

 

Handler 成员此时已经集齐,是时候放到一个线程里让其运转起来了。 这里我们分析ActivityThread的源码,并提取 handler 相关的部分。

package com.android;

public final class ActivityThread {


        static volatile Handler sMainThreadHandler;  // set once in main()
        final H mH = new H();


        public static void main(String[] args) {

            Looper.prepareMainLooper();

            ActivityThread thread = new ActivityThread();


            Looper.loop();
        }


        static class H extends Handler {

            public void handleMessage(Message msg) {
                System.out.println("msg "+msg.what);
            }
        }

        ActivityThread() {
            System.out.println("构造ActivityThread");
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int count =0;
                    while(count <10){

                        System.out.println("构建message"+count);
                        Message msg = new Message();
                        msg.what = count;
                        mH.sendMessage( msg );

                        count++;
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            });
            thread.start();
        }

}

为了模拟 handler sendMessage 给ActivityThread的主线程, 我们在 ActivityThread 的构造函数里, 创建一个子线程, 并用关联主线程的handler发送消息到主线程的消息队列。

为模拟ActivityThread 的启动过程 再增加一个Main.java

package com.android;

public class Main {

    public static void main(String[] args) {
   // write your code here

        ActivityThread.main( args);


    }
}

在android 源码中, 是用反射的方式调用ActivityThread 的main 函数, 这里我们为了方便 直接从Main.main 来启动。

参考资料:

1.《深入理解Android内核设计思想》 林学森

2. https://blog.csdn.net/zhangke3016/article/details/75923323

 

你可能感兴趣的:(android开发)