手写Android-Handler

计算机软件开发 2024-9-19 20:39:46 105 0 来自 中国
Handler机制,是Android系统的消息队列,一样平常用于处理惩罚主线程的页面绘制等消息处理惩罚。
媒介

Handler除了Java层外,另有Native的部门,但我本领有限,只能仿写一个Java层的Handler,而且支持延时消息。项目地点:MiniHandler
注:由于消息机制须要利用一个while死循环来让线程不能结束,以是直接将MiniHandler在Android主线程中利用会卡住主线程,以是须要用一个子线程来运行MiniHandler,一样平常利用HandlerThread,对应到MiniHandler的MiniHandlerThread
简单先容


  • 延时消息功能:利用DelayQueue实现,它须要队列中的消息实体实现一个Delayed接口,它继承于Comparable接口,它要求复写一个getDelay()方法,返回延时多长毫秒。以及须要复写compareTo()方法,用于比力2个消息谁先谁后,来决定队列中的消息排序。
类结构先容

  • Looper,轮训器,内部包罗一个MessageQueue消息队列,而且利用ThreadLocal将每个线程绑定一个Looper。以是一个线程只有一个Looper,一个Looper也只有一个MessageQueue消息队列
  • MessageQueue,消息队列,利用DelayQueue实现队列功能,支持延时消息
  • Message,消息实体类,利用享元模式支持消息对象复用
  • MiniHandler,消息处理惩罚器以及消息发送器
  • MiniHandlerThread,原自Android源码中的HandlerThread,改用MiniHandler实现,就是一个带有Handler事件循环的子线程
原理

  • Handler,发送Message消息到MessageQueue,会被Looper轮训器取出
  • Looper轮训器中,有一个while循环,不停从MessageQueue消息队列中取出消息举行处理惩罚,如果队列中没有消息,MessageQueue会壅闭当火线程
  • Handler处理惩罚完消息,Message消息回收到池中,复用消息能提高服从,以及淘汰对象创建
根本利用

MiniHandler的API和Handler的划一,2者的Java层API只是类名差异。
/** * Toast任务 */public static final int ACTION_TOAST = 1;/** * 延时任务 */public static final int ACTION_DELAY = 2;////事件处理惩罚线程MiniHandlerThread handlerThread = new MiniHandlerThread("handler-thread");handlerThread.start();//创建MiniHandler实例,并绑定到MiniHandlerThreadMiniHandler  eventHandler = new MiniHandler(mHandlerThread.getLooper()) {    @Override    public void handleMessage(Message message) {        super.handleMessage(message);        long action = message.what;        if (action == ACTION_TOAST) {            String msg = message.obj.toString();            ToastUtil.toast(getApplicationContext(), msg);        } else if (action == ACTION_DELAY) {            String delayMsg = message.obj.toString();            ToastUtil.toast(getApplicationContext(), delayMsg);        }    }};//发消息到立即实行事件线程eventHandler.sendMessage(Message.obtain(ACTION_TOAST, "Toast~"));//大概eventHandler.post(new Runnable() {    @Override    public void run() {      ToastUtil.toast(getApplicationContext(), 延时消息~);    }});//发送延时消息到事件线程eventHandler.sendMessageDelayed(Message.obtain(ACTION_DELAY, "延时消息~"), 2000);//大概eventHandler.postDelayed(new Runnable() {    @Override    public void run() {      ToastUtil.toast(getApplicationContext(), 延时消息~);    }}, 1000);//退出MiniHnadlerThreadhandlerThread.quitSafely();源码

Message消息实体

消息实体类,利用享元模式支持消息对象复用。为了支持延时消息,消息实体,须要实现一个Delayed接口,它继承于Comparable接口,它要求复写一个getDelay()方法,返回延时多长毫秒。以及须要复写compareTo()方法,用于比力2个消息谁先谁后,来决定队列中的消息排序。
/** * 消息事件实体 */public class Message implements Delayed {    /**     * 利用中的标记位     */    static final int FLAG_IN_USE = 1;    int flags;    /**     * 为了形成消息链表     */    Message next;    /**     * 对象锁     */    public static final Object sPoolSync = new Object();    /**     * 消息链表的头节点     */    private static Message sPool;    /**     * 当前链表中数据的个数     */    private static int sPoolSize = 0;    /**     * 统共可利用的消息链表巨细     */    private static final int MAX_POOL_SIZE = 50;    /**     * 消息的标识     */    public long what;    /**     * 消息的附件     */    public Object obj;    /**     * 消息的处理惩罚器     */    public MiniHandler target;    /**     * 要实行的任务,可为null     */    public Runnable callback;    /**     * 指定的实行时间,毫秒值     */    public long workTimeMillis;    /**     * 回收Message     */    void recycleUnchecked() {        //把标记设置为利用中        flags = FLAG_IN_USE;        //清算全部字段        what = 0;        obj = null;        target = null;        callback = null;        workTimeMillis = 0;        synchronized (sPoolSync) {            if (sPoolSize < MAX_POOL_SIZE) {                next = sPool;                sPool = this;                sPoolSize++;            }        }    }    /**     * 创建一个Message对象     */    public static Message obtain() {        synchronized (sPoolSync) {            //判定头节点是否null            if (sPool != null) {                //取出头节点                Message m = sPool;                //将头节点的下一个作为最新的头节点                sPool = m.next;                //设置须要返回的消息的next为空                m.next = null;                //打扫利用中的标记位                m.flags = 0;                sPoolSize--;                return m;            }        }        //如果消息链表为空 创建新的message        return new Message();    }    /**     * 创建一个Message对象,并绑定处理惩罚它的Handler     */    public static Message obtain(MiniHandler handler) {        return obtain(handler, 0);    }    /**     * 创建一个Message对象,并绑定处理惩罚它的Handler、消息标识what     */    public static Message obtain(MiniHandler handler, long what) {        return obtain(handler, what, null);    }    /**     * 创建一个Message对象,绑定消息标识what     */    public static Message obtain(long what) {        return obtain(what, null);    }    /**     * 创建一个Message对象,绑定消息标识what、消息附件obj     */    public static Message obtain(long what, Object obj) {        return obtain(null, what, obj);    }    /**     * 创建一个Message对象,并绑定处理惩罚它的Handler、消息标识what、消息附件obj     */    public static Message obtain(MiniHandler handler, long what, Object obj) {        Message message = obtain();        message.target = handler;        message.what = what;        message.obj = obj;        return message;    }    @Override    public long getDelay(TimeUnit unit) {        return unit.convert(workTimeMillis                - System.currentTimeMillis(), TimeUnit.MILLISECONDS);    }    @Override    public int compareTo(Delayed o) {        return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));    }}MessageQueue消息队列

消息队列,利用DelayQueue实现队列功能,支持延时消息
public class MessageQueue {    /**     * 是否退出     */    volatile boolean isQuit;    /**     * 消息队列     */    private final BlockingQueue<Message> mMessageQueue = new DelayQueue<>();    /**     * 消息入队     */    public boolean enqueueMessage(Message message, long uptimeMillis) {        try {            message.workTimeMillis = uptimeMillis;            mMessageQueue.put(message);            return true;        } catch (InterruptedException e) {            e.printStackTrace();        }        return false;    }    /**     * 拿出一条消息     */    public Message next() {        try {            //如果队列中没有消息,就会壅闭在这里            return mMessageQueue.take();        } catch (InterruptedException e) {            e.printStackTrace();        }        return null;    }    /**     * 移除队列中指定Handler的未实行的回调和消息     */    public final void removeCallbacksAndMessages(MiniHandler handler) {        if (handler == null) {            return;        }        List<Message> targetMessages = new ArrayList<>();        for (Message message : mMessageQueue) {            if (message.target == handler) {                targetMessages.add(message);            }        }        mMessageQueue.removeAll(targetMessages);    }    public void quit() {        mMessageQueue.clear();        isQuit = true;    }}Looper轮训器

轮训器,内部包罗一个MessageQueue消息队列,而且利用ThreadLocal将每个线程绑定一个Looper。以是一个线程只有一个Looper,一个Looper也只有一个MessageQueue消息队列
public class Looper {    private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();    /**     * 消息队列     */    final MessageQueue mMessageQueue;    private Looper() {        //一个线程,只有一个Looper,一个Looper也只有一个消息队列        mMessageQueue = new MessageQueue();    }    /**     * 把当火线程和Looper举行绑定     */    public static void prepare() {        Looper looper = sThreadLocal.get();        if (looper != null) {            throw new RuntimeException("一个线程只能绑定一个Looper,请确保prepare方法在一个线程中只调用一次");        }        sThreadLocal.set(new Looper());    }    /**     * 获取当火线程的Looper     */    public static Looper myLooper() {        return sThreadLocal.get();    }    /**     * 开始循环从队列中取出消息     */    public static void loop() {        //获取当火线程的轮询器        Looper looper = myLooper();        MessageQueue queue = looper.mMessageQueue;        while (!queue.isQuit) {            Message message = queue.next();            try {                message.target.dispatchMessage(message);            } finally {                //回收Message对象                message.recycleUnchecked();            }        }    }    /**     * 安全退出,会等全部事件都实行完,再关闭     */    public void quitSafely() {        mMessageQueue.quit();    }}MiniHandler消息处理惩罚器

消息处理惩罚器以及消息发送器
public class MiniHandler {    /**     * 消息队列     */    private final MessageQueue mMessageQueue;    /**     * 事件回调,可以选择构造时传入一个Callback,就可以不须要复写handleMessage()方法举行处理惩罚     */    private MiniHandler.Callback mCallback;    public MiniHandler() {        this(Looper.myLooper());    }    public MiniHandler(Callback callback) {        Looper looper = Looper.myLooper();        //Looper没有绑定        if (looper == null) {            throw new RuntimeException(                    "Can't create handler inside thread " + Thread.currentThread()                            + " that has not called Looper.prepare()");        }        mMessageQueue = looper.mMessageQueue;        mCallback = callback;    }    public MiniHandler(Looper looper) {        //Looper没有绑定        if (looper == null) {            throw new RuntimeException(                    "Can't create handler inside thread " + Thread.currentThread()                            + " that has not called Looper.prepare()");        }        mMessageQueue = looper.mMessageQueue;    }    public interface Callback {        /**         * @param msg A {@link android.os.Message Message} object         * @return True if no further handling is desired         */        boolean handleMessage(Message msg);    }    /**     * 移除队列中指定Handler的未实行的回调和消息     */    public final void removeCallbacksAndMessages() {        mMessageQueue.removeCallbacksAndMessages(this);    }    /**     * 发送消息到消息队列中     */    public boolean sendMessage(Message message) {        return sendMessageDelayed(message, 0);    }    /**     * 在主线程实行一个Runnable     */    public final boolean post(Runnable task) {        return sendMessageDelayed(getPostMessage(task), 0);    }    /**     * 延伸一段时间后,在主线程实行一个Runnable     *     * @param delayMillis 延时时间,毫秒值     */    public final boolean postDelayed(Runnable task, long delayMillis) {        return sendMessageDelayed(getPostMessage(task), delayMillis);    }    /**     * 获取一个带Runnable任务的Message     */    private static Message getPostMessage(Runnable task) {        Message m = Message.obtain();        m.callback = task;        return m;    }    /**     * 发送延时消息     *     * @param message     消息     * @param delayMillis 延时时间     */    public final boolean sendMessageDelayed(Message message, long delayMillis) {        if (delayMillis < 0) {            delayMillis = 0;        }        return sendMessageAtTime(message, System.currentTimeMillis() + delayMillis);    }    public boolean sendMessageAtTime(Message message, long uptimeMillis) {        MessageQueue queue = this.mMessageQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                    this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);            return false;        }        return enqueueMessage(queue, message, uptimeMillis);    }    private boolean enqueueMessage(MessageQueue queue, Message message, long uptimeMillis) {        message.target = this;        return queue.enqueueMessage(message, uptimeMillis);    }    /**     * 分发消息给Handler举行处理惩罚     */    void dispatchMessage(Message message) {        //如果是post()或postDelayed()发出的任务,则实行这个任务        if (message.callback != null) {            handleCallback(message);        } else {            //如果在Handler构造时传入了Callback,则回调这个Callback            if (mCallback != null) {                if (mCallback.handleMessage(message)) {                    return;                }            }            //都没有,则调用handleMessage(),Handler的子类可以复写该方法举行事件处理惩罚            handleMessage(message);        }    }    /**     * 实行Message绑定的任务     */    private static void handleCallback(Message message) {        message.callback.run();    }    /**     * 子类重写该方法举行处理惩罚消息     */    public void handleMessage(Message message) {    }}MiniHandlerThread

原自Android源码中的HandlerThread,改用MiniHandler实现,就是一个带有Handler事件循环的子线程
/** * A {@link Thread} that has a {@link Looper}. * The {@link Looper} can then be used to create {@link MiniHandler}s. * <p> * Note that just like with a regular {@link Thread}, {@link #start()} must still be called. */public class MiniHandlerThread extends Thread {    int mPriority;    int mTid = -1;    Looper mLooper;    private MiniHandler mHandler;    public MiniHandlerThread(String name) {        super(name);        mPriority = Process.THREAD_PRIORITY_DEFAULT;    }    /**     * Constructs a HandlerThread.     *     * @param name     * @param priority The priority to run the thread at. The value supplied must be from     *                 {@link android.os.Process} and not from java.lang.Thread.     */    public MiniHandlerThread(String name, int priority) {        super(name);        mPriority = priority;    }    /**     * Call back method that can be explicitly overridden if needed to execute some     * setup before Looper loops.     */    protected void onLooperPrepared() {    }    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }    /**     * This method returns the Looper associated with this thread. If this thread not been started     * or for any reason isAlive() returns false, this method will return null. If this thread     * has been started, this method will block until the looper has been initialized.     *     * @return The looper.     */    public Looper getLooper() {        if (!isAlive()) {            return null;        }        // If the thread has been started, wait until the looper has been created.        synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }    /**     * @return a shared {@link MiniHandler} associated with this thread     * @hide     */    public MiniHandler getThreadHandler() {        if (mHandler == null) {            mHandler = new MiniHandler(getLooper());        }        return mHandler;    }    /**     * Quits the handler thread's looper safely.     * <p>     * Causes the handler thread's looper to terminate as soon as all remaining messages     * in the message queue that are already due to be delivered have been handled.     * Pending delayed messages with due times in the future will not be delivered.     * </p><p>     * Any attempt to post messages to the queue after the looper is asked to quit will fail.     * For example, the {@link MiniHandler#sendMessage(Message)} method will return false.     * </p><p>     * If the thread has not been started or has finished (that is if     * {@link #getLooper} returns null), then false is returned.     * Otherwise the looper is asked to quit and true is returned.     * </p>     *     * @return True if the looper looper has been asked to quit or false if the     * thread had not yet started running.     */    public boolean quitSafely() {        Looper looper = getLooper();        if (looper != null) {            looper.quitSafely();            return true;        }        return false;    }    /**     * Returns the identifier of this thread. See Process.myTid().     */    public int getThreadId() {        return mTid;    }}
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2025-4-19 19:15, Processed in 0.096130 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表