Handler是什么?有什么用?

Android定义的一套同进程中线程间消息传递机制
通常用来把子线程中的UI更新消息,传递给主线程更新UI;当然也可以反过来使用,只是会麻烦一些。
Handler消息机制是由一组MessageQueue、Message、Looper、Handler共同组成的。

如果说Binder/socket是android必须掌握的IPC机制,那么Handler则是必须掌握的消息机制。

子线程使用Handler例子
class LooperThread extends Thread {    public Handler mHandler;    public void run() {        Looper.prepare();        // Step 1: 创建Handler        mHandler = new Handler() {            public void handleMessage(Message msg) {                //处理即将发送过来的消息                System.out.println("thread id="+Thread.currentThread().getId());            }        };        Looper.loop();    }}// Step 2: 创建并启动LooperThread线程,内部包含LooperLooperThread looperThread = new LooperThread();looperThread.start();// Step 3: 发送消息looperThread.mHandler.sendEmptyMessage(10);

可以看到,在子线程中使用Handler比在主线程中使用多了Looper.prepare();和Looper.loop();的步骤。这个之后在其他文章中叙述。

拓展问题:必须是Handler吗?还有哪些方式?

首先我们来看看经常用的有哪些异步方式。

  • 1、runOnUiThread
  • 2、View.post
  • 3、AsyncTask
1、Activity.runOnUiThread(Runnable)

Activity.java

    public final void runOnUiThread(Runnable action) {        if (Thread.currentThread() != mUiThread) {            mHandler.post(action);        } else {            action.run();        }    }

看来还是Handler,如果是主线程则马上执行Run方法,如果不是继续看Handler的代码

    public final boolean post(@NonNull Runnable r) {       return  sendMessageDelayed(getPostMessage(r), 0);    }        public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {        return sendMessageDelayed(getPostMessage(r), delayMillis);    }    

postDelayed我们经常用,和post都是调用的sendMessageDelayed方法,只是延时为0而已

    public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {        if (delayMillis < 0) {            delayMillis = 0;        }        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);    }    public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {        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);    }    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,            long uptimeMillis) {        msg.target = this;        msg.workSourceUid = ThreadLocalWorkSource.getUid();        if (mAsynchronous) {            msg.setAsynchronous(true);        }        return queue.enqueueMessage(msg, uptimeMillis);    }    

注意SystemClock.uptimeMillis()是开机到现在的时间
enqueue就是入队嘛

    public Handler(@Nullable Callback callback, boolean async) {        if (FIND_POTENTIAL_LEAKS) {            final Class<? extends Handler> klass = getClass();            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                    (klass.getModifiers() & Modifier.STATIC) == 0) {                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                    klass.getCanonicalName());            }        }        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;        mCallback = callback;        mAsynchronous = async;    }

注意这个mQueue成员变量是在Handler构造函数中初始化的,从Looper来的

2、View.post(Runnable)

View.java

    public boolean post(Runnable action) {        final AttachInfo attachInfo = mAttachInfo;        if (attachInfo != null) {            return attachInfo.mHandler.post(action);        }        // Postpone the runnable until we know on which thread it needs to run.        // Assume that the runnable will be successfully placed after attach.        getRunQueue().post(action);        return true;    }    public boolean postDelayed(Runnable action, long delayMillis) {        final AttachInfo attachInfo = mAttachInfo;        if (attachInfo != null) {            return attachInfo.mHandler.postDelayed(action, delayMillis);        }        // Postpone the runnable until we know on which thread it needs to run.        // Assume that the runnable will be successfully placed after attach.        getRunQueue().postDelayed(action, delayMillis);        return true;    }    

可以看到View的post和postDelayed的方法都是走的一样的路子,也看到了Handler的出现,但是第二条路 简单地说一下吧,细节不在这儿一一贴出了。我们使用 View.post() 时,其实内部它自己分了两种情况处理,当 View 还没有 attachedToWindow 时,通过 View.post(Runnable) 传进来的 Runnable 操作都先被缓存在 HandlerActionQueue,然后等 View 的 dispatchAttachedToWindow() 被调用时,就通过 mAttachInfo.mHandler 来执行这些被缓存起来的 Runnable 操作。从这以后到 View 被 detachedFromWindow 这段期间,如果再次调用 View.post(Runnable) 的话,那么这些 Runnable 不用再缓存了,而是直接交给 mAttachInfo.mHanlder 来执行。

3、AsyncTask

AsyncTask是一个轻量级的异步实现,可以轻松实现工作线程和UI线程的通信
他实现的原理也是 线程池 + Handler 具体怎么实现的去找源码吧

总结

到这儿我们发现好像这些异步类\方法只要涉及到了与主线程做通信,都使用了Handler,这就可以回答刚才的拓展问题了,他是Android设计之初就封装的一套消息传递机制,不用它还真不行。

更多相关文章

  1. 浅析Android中的消息机制-解决:Only the original thread that cr
  2. Android异步消息机制之Handler
  3. Android的Handler机制详解3_Looper.looper()不会卡死主线程
  4. Android之Handler用法总结
  5. Android开发之消息处理机制(一)——Handler
  6. Android异步加载图像小结 (含线程池,缓存方法)
  7. android 面试题集
  8. Titanium 使用刘明星的Jpush module做android端的消息推送
  9. [Innost]Android深入浅出之Binder机制

随机推荐

  1. 聊聊职业规划,怀疑人生的那种!
  2. 年轻人,请别再乱花钱了!
  3. 同伴压力,大学生一定摆脱这种思维
  4. 别再问我Python怎么操作Word了!
  5. 最近的状况,顺便聊聊互联网的噪音。
  6. 工作之后,如何构建知识体系?
  7. 来自Kaggle金牌得主的Python数据挖掘框架
  8. 大学中,最让我受益的一本书。
  9. 看完这篇Python操作PPT总结,从此使用Pytho
  10. 太赞了!对标阿里‘60w’年薪Android开发笔