欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Handler、Looper、Message、MessageQueue

程序员文章站 2022-07-14 19:57:55
...

看一个例子:

public class MainActivity extends AppCompatActivity {

    private TextView textView = null;
    private TLHThread tlhThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        tlhThread = new TLHThread("TLHThread");
        tlhThread.start();
        Log.e("tlh", "onCreate");

    }

    @Override
    protected void onResume() {
        super.onResume();
        tlhThread.mHandhler.sendEmptyMessage(1);
        Log.e("tlh", "onResume");
    }

    class TLHThread extends Thread {

        public Handler mHandhler;

        public TLHThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            super.run();
            Looper.prepare();
            mHandhler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Log.e("tlh", Thread.currentThread().getName());
                }
            };
            Looper.loop();

        }
    }
}

信息打印(注意handleMessage打印当前线程的名称)

09-28 08:29:55.424 9876-9876/? E/tlh: onCreate
09-28 08:29:55.428 9876-9876/? E/tlh: onResume
09-28 08:29:55.428 9876-13115/? E/tlh: TLHThread
消息的处理不是在Main线程,而是在TLHThread线程中。然后,我把Looper.prepare();和Looper.loop();还有public void handleMessage(Message msg);的相对位置的改变,以及相对对应的打印信息:

1.Looper.prepare()和Looper.loop()在Handler初始化之前:

    Looper.prepare();
            Log.e("tlh", " Looper.loop() start");
            Looper.loop();
            Log.e("tlh", " Looper.loop() end");
            mHandhler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Log.e("tlh", Thread.currentThread().getName());
                }
            };

打印信息(这里其实是有问题的,Log.e("tlh", " Looper.loop() end")一直没有运行,想想为什么?会有什么后果?):

09-28 08:59:07.190 21166-21166/? E/tlh: onCreate
09-28 08:59:07.191 21166-22972/? E/tlh:  Looper.loop() start
09-28 08:59:07.195 21166-21166/? E/tlh: onResume

2.Handler初始化在Looper.prepare()和Looper.loop()之前:
            mHandhler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Log.e("tlh", Thread.currentThread().getName());
                }
            };
            Looper.prepare();
            Looper.loop();


打印信息(系统抛异常了,要求我们在初始化Handler之前调用Looper.prepare()):

09-28 09:06:47.254 27410-27432/? E/AndroidRuntime: FATAL EXCEPTION: TLHThread
                                                   Process: ampalexa.amp.action.com.testlooper, PID: 27410
                                                   java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
                                                       at android.os.Handler.<init>(Handler.java:200)
                                                       at android.os.Handler.<init>(Handler.java:114)
                                                       at ampalexa.amp.action.com.testlooper.MainActivity$TLHThread$1.<init>(MainActivity.java:50)
                                                       at ampalexa.amp.action.com.testlooper.MainActivity$TLHThread.run(MainActivity.java:50)






一个线程中可以有一个Looper,Looper中有一个MessageQueue,MessageQueue中是很多的Message。

至于Handler,就负责将Message压到MessageQueue中去,Looper轮询MessageQueue中的Message,然后回调Message的Callback或者Handler的handlerMessage方法。


我们在UI线程中使用Handler完成异步任务的时候基本这样:

    private Handler mHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            
        }
    };

    new Thread(new Runnable() {
            @Override
            public void run() {
                mHandler.sendEmptyMessage(0);
            }
        }).start();

在调用Handler的构造方法时都做了那些事?看源码:

    public Handler() {
        this(null, false);
    }

  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;
    }

 public static Looper myLooper() {
        return sThreadLocal.get();
    }
Handler的构造方法中,拿到了UI线程的Looper和Looper中的MessageQueue。



接下来,我们看下Handler发送Message的时候做了什么?看源码:

 public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }
 public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }

 public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

  public boolean sendMessageAtTime(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(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

层层调用,发送空信息的时候,系统自动创建了一个Message将我们制定的那个what赋值到系统创建的Message,在然后将Message压送到MessageQueue中去了。



至于在哪里调用handlerMessage的呢?是在Looper的loop方法中:(看源码)

 public static void 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.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycle();
        }
    }

注意看中间的:msg.target.dispatchMessage(msg);

msg就是从MessageQueue中取出来的消息

target就是Looper对应的Handler

接下来定位到Handler的dispatchMessage方法:

 public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

dispatchMessage方法中判断了Message的callback是否为空,这里的Message的Callback我们平时其实也有用,在调用Handler中的post方法传入Runnable的时候其实就使用了。接下来就是将Message通过Handler中的接口Callback或者handleMessage方法将Message回调出去处理。

public interface Callback {
        public boolean handleMessage(Message msg);
    }
    
    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }


相关标签: Looper Handler