android 多个子线程有多个loop吗

2025-03-10 10:15:24
推荐回答(1个)
回答1:

handlerB当然不能接收到taskA中的handlerA发送的message,可能有同学会说了,handlerA和handlerB都是在主线程中创建的handler,他们都关联于主线程,每个线程都有一个队列messageQueue,looper管理这个队列并且分发消息,无论是handlerA还是handlerB都是发送消息到主线程中的messageQueue, 并且这两个handler的代码也是一样的,handlerA所在的视图处于后台,视图B在前台,handlerB应该能够接受handlerA发送的消息并且处理啊,测试一下,果然视图b中虽然没有启动taskB,但是依然弹出了toast,难道这种说法是对的吗?

当然不对,主要有这么两个问题。

  第一个问题:handlerB能否接收到handlerA发送的消息?

  不能,看看Message的创建方式

复制代码
Message mes = new Message();
mHandler.sendMessage(mes);
//********************************
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}

//********************************
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)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
复制代码

通过代码我们可以看到Message会指定它的target为发送他的handler

另外一种方式:

复制代码
Message mes2 = mHandler.obtainMessage();
mes2.sendToTarget();

//**********************************
public final Message obtainMessage()
{
return Message.obtain(this);
}
//***********************************
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;

return m;
}
复制代码
这两种创建方式都是一样的。

再来看一下消息是怎么分发的?

Looper会不断的轮询消息队列,将消息发送给响应的handler进行处理

复制代码
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
msg.recycle();
}
}
}
//*****************************************************************************

复制代码

  看上面的红色标注的代码,他会调用这个Message的target的dispatchMessage(msg)分发,上面就说过了这个target就是发送这个消息的handler本身.

复制代码
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
复制代码
至此结束,handlerB根本不会得到handlerA的消息

第二个问题,既然handlerB不能获得handlerA的消息,那么又是如何弹的toast呢?

复制代码

public static Toast makeText(Context context, CharSequence text, int duration) {
Toast result = new Toast(context);

LayoutInflater inflate = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
tv.setText(text);

result.mNextView = v;
result.mDuration = duration;

return result;
}
//*********************************************
public void show() {
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}

INotificationManager service = getService();

String pkg = mContext.getPackageName();

TN tn = mTN;

try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}