MainActivity:
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");
}
}
}
服务:
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()));
mExe.submit(new Runnable() {
@Override
public void run() {
System.out.println(
new StringBuilder(" NonUI Thread - What? - ")
.append(msg.what)
.append("Data? - ")
.append(msg.peekData() == null)
.append(" KeySet size? - ")
.append(msg.getData().keySet().size()));
}
});
}
};
private final Messenger mInMessenger = new Messenger(mInHandler);
@Override
public IBinder onBind(Intent intent) {
return mInMessenger.getBinder();
}
}
输出:
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和NON UI Thread的输出相同。
我的Java知识已经结束,希望有人可以理解为我解释这一点。
答案 0 :(得分:1)
您使用Message.obtain();
从全局池中返回一个新的Message实例。
创建新线程时,方法handleMessage(Message msg)
完成执行,仍然属于全局池的对象Message正在回收。所以在新线程中这个对象已经是空的
在您的服务中,您可以这样做:
@Override
public void handleMessage(Message msg) {
final Message message = new Message();
message.copyFrom(msg);
//your code
}
或者您可以将Message
对象映射到您自己的自定义对象中。最好仅将Message
对象用于通过Handler