Android面试需要知道的问题安卓开发知识mqtt

两张图看透Android Handler使用与机制

2016-09-13  本文已影响386人  KaelQ

1.Handler的使用

public class MainActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       final Handler handler=new Handler(){
           @Override
           public void handleMessage(Message m){
               //更新ui操作
           }
       };
       new Thread(){//子线程开启
           @Override
           public void run(){
               Message m=new Message();
               handler.sendMessage(m);
           }
       };
   }
}

2.Handler的机制

2.1 被消息传递的线程A准备

public static void prepare() {
    prepare(true);
}
private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

总的来说,prepare干了两件事:创建MessageQueue和绑定当前线程。

public static void loop() {
      // 拿到与当前线程关联的looper对象
        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
            ...................................
            msg.target.dispatchMessage(msg);
            ..........................................
            msg.recycleUnchecked();// 回收Message对象
        }
    }

总的来说,loop干了三件事:
1.拿到当前线程的looper。
2.根据looper拿到MessageQueue。
3.使用for循环对MessageQueu进行无限循环询问。
在for循环中也主要干了三件事:
1.从消息队列中取消息,如果没有就阻塞。
2.调用msg.target.dispatchMessage(msg)方法对Message进行处理。
3.处理完成后调用msg.recycleUnchecked()回收资源。

public Handler(Looper looper, Callback callback, boolean async){
        mLooper = looper;
        // 与这个Handler关联的Looper中的消息队列
        mQueue = looper.mQueue;
        ...............
}

创建Handler时将当前线程的Looper和Looper中的MessageQueue取到。

2.2 传递消息的线程B准备

public boolean sendMessageAtTime(Message Message, long uptimeMillis) {
        // 1. 获取Hndler中的消息队列
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        // 2. 将要发送消息和时间入队
        return enqueueMessage(queue, Message, uptimeMillis);
    }

总的来说,做了两件事:
1.获取handler中的MessageQueue。
2.调用enqueueMessage方法。
enqueueMessage()方法代码如下:

 private boolean enqueueMessage(MessageQueue queue, Message Message, long uptimeMillis) {
        // 1. 将Handler赋值给Message的target 
        Message.target = this;
        if (mAsynchronous) {
            Message.setAsynchronous(true);
        }
        // 2. 将Message加入到消息队列中(还有Handler)
        return queue.enqueueMessage(Message, uptimeMillis);
    }

总的来说,做了两件事:
1.将handler赋值给Message.target。
2.并且将Message放入MessageQueue中。

2.3 线程间通信

public void dispatchMessage(Message msg) {
     ..........
     handleMessage(msg);
 }

在其中调用了handleMessage()方法,并且handleMessage()方法是个空方法,没有内容。所以我们只用重写这个方法就可以对线程B返回的消息进行处理了。

3.一些问题

上一篇下一篇

猜你喜欢

热点阅读