Java 为什么消息在传递到另一个线程时会丢失其内容?
在开发Android应用程序的过程中,我发现(在我看来)一个非常奇怪的行为。 通过将消息对象(android.os.message)传递到另一个线程,它将丢失其所有内容。也许有人能给我解释一下为什么会这样?我编写了一个示例应用程序来说明这个问题: 主要活动:Java 为什么消息在传递到另一个线程时会丢失其内容?,java,android,Java,Android,在开发Android应用程序的过程中,我发现(在我看来)一个非常奇怪的行为。 通过将消息对象(android.os.message)传递到另一个线程,它将丢失其所有内容。也许有人能给我解释一下为什么会这样?我编写了一个示例应用程序来说明这个问题: 主要活动: package com.test.bundletest; import android.content.ComponentName; import android.content.Intent; import android.conten
package com.test.bundletest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private Messenger mOutMsger;
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mOutMsger = new Messenger(service);
System.out.println("Connected");
sendMultipleMessages(10);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(this, MyService.class));
bindService(new Intent(this, MyService.class), mConnection, BIND_AUTO_CREATE);
}
private void sendMultipleMessages(int messageCount){
if (mOutMsger!=null){
for (int i = 0; i<messageCount; i++){
Message msg = Message.obtain();
Bundle b = new Bundle();
b.putString("test", "Just a test");
msg.setData(b);
msg.what = i;
try {
mOutMsger.send(msg);
System.out.println("Message sent");
} catch (RemoteException e) {
e.printStackTrace();
}
}
}else {
System.out.println("Messenger was null");
}
}
}
输出:
8751-8751/com.test.bundletest I/System.out: Connected
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 0Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 1Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 2Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 3Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 4Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 5Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 6Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 7Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 8Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out: UI Thread - What? - 9Data? - false KeySet size? - 1
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out: NonUI Thread - What? - 0Data? - true KeySet size? - 0
更奇怪的是,如果我在处理邮件之前复制了邮件,这种情况就不会发生:
package com.test.bundletest;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyService extends Service {
private ExecutorService mExe = Executors.newSingleThreadExecutor();
@SuppressLint("HandlerLeak")
private final Handler mInHandler = new Handler(){
@Override
public void handleMessage(final Message msg) {
System.out.println(
new StringBuilder(" UI Thread - What? - ")
.append(msg.what)
.append("Data? - ")
.append(msg.peekData() == null)
.append(" KeySet size? - ")
.append(msg.getData().keySet().size()));
final Message msg2 = Message.obtain(msg);
mExe.submit(new Runnable() {
@Override
public void run() {
System.out.println(
new StringBuilder(" NonUI Thread - What? - ")
.append(msg2.what)
.append("Data? - ")
.append(msg2.peekData() == null)
.append(" KeySet size? - ")
.append(msg2.getData().keySet().size()));
}
});
}
};
private final Messenger mInMessenger = new Messenger(mInHandler);
@Override
public IBinder onBind(Intent intent) {
return mInMessenger.getBinder();
}
}
以这种方式运行,UI线程和非UI线程的输出是相同的
我的Java知识已经不多了,希望有人能给我解释清楚。您使用
Message.get()从全局池返回新消息实例的代码>
创建新线程时,方法handleMessage(Message msg)
完成执行,仍然属于全局池的对象消息正在循环。因此,在新线程中,该对象已为空
在您的服务中,您可以这样做:
@Override
public void handleMessage(Message msg) {
final Message message = new Message();
message.copyFrom(msg);
//your code
}
或者,您可以将消息
对象映射到您自己的自定义对象中。最好仅使用消息
对象通过处理程序进行数据传输
谢谢!似乎正是描述的方式。消息对象在handleMessage(消息消息消息)完成后被回收。如果我延迟方法的结束,数据将被保留。遗憾的是,文档中显然没有描述此过程。
@Override
public void handleMessage(Message msg) {
final Message message = new Message();
message.copyFrom(msg);
//your code
}