哎,最近被大佬问了一个关于Handler的问题,支支吾吾了半天,发现自己又是没有深入了解,乘着有动力,抓紧复习一波。
handler是Android方面的消息机制。

对于开发者来说(比如我),刚学习Android的时候,总是会遇到非UI线程无法操作view的情况。往往遇到这种时候,就需要用到handler去处理更新view。但其实handler的用途远远不止这些。

消息机制的四个点:Handler(处理者)、Message(消息体)、MessageQueue(消息队列)和Looper(一个循环的泵)。

  1. Handler 如何跨进程传递消息的呢
    比如当前有两个线程:A代表主线程,B代表子线程。B执行一个耗时任务,结束了将结果返回给A。这个过程是如何实现的呢?
private Handler mHandler = new Handler(){
       @Override
       public void handleMessage(Message msg) {
           switch (msg.what){
               case 1:
                   break;
               default:
                   break;
           }
           super.handleMessage(msg);
       }
   };
 new Thread(new Runnable() {
            @Override
            public void run() {
                //very 耗时的操作
                //····
                //···
                //··
                Message msg = mHandler.obtainMessage();
                msg.what = 1;
                msg.obj = "result";
                mHandler.sendMessage(msg);

            }
        }).start();

当创建一个Handler对象的时候,在activity中直接new Handler()创建的handler对象默认最终走到

  public Handler(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 that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

可以看到Looper.myLooper();方法创建一个looper对象,这个looper对象查看方法可知

 public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

是通过ThreadLocal获取的,ThreadLoacl是什么呢?你可以理解成一个根据当前线程的容器,可以存储任何数据。但是这些数据存储提取的前提是,只在当前线程,别的线程可以吗?不行。

所以这里的sThreadLocal.get();是从哪里获取的呢?这里牵扯到主线程(UI)的问题。当一个activity创建的时候,ActivityThread默认会调用Looper.prepareMainLooper();和Looper.loop();方法,这两个方法默认已经将主线程的Looper和MessageQueue已经搭好了,并且保存在主线程的ThreadLocal中去了。(ThreadLocal具体可以看Android开发艺术探索,或者以后我填坑

标签: none

添加新评论