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) {
}
推荐阅读
-
AsyncTask陷阱之:Handler,Looper与MessageQueue的详解
-
Android中Handler与Message的简单实例
-
android的消息处理机制(图文+源码分析)—Looper/Handler/Message
-
AsyncTask陷阱之:Handler,Looper与MessageQueue的详解
-
Handler,Looper,MessageQueue流程梳理
-
Android消息处理机制Looper和Handler详解
-
Android Handler Message 里面的message.what, message.arg1,message.obj,obtainMessage, message.setData的使用
-
Android Studio 之 Android消息机制 之简单Demo --- 使用Handler和Message类来完成消息传递
-
Android异步2:深入详解 Handler+Looper+MessageQueue
-
Android消息机制(3)- Handler和Looper