Messenger是一种轻量级的IPC方案,在进程间传送Message对象,Message中可以传送Bundle对象,Bundle中可以传送我们实现了Parcelable接口的对象。使用Messenger不会出现并发读写问题,因为Messenger是以串行方式工作的,所以如果有大量的请求,不适合使用Messenger。
Messenger有两个构造方法:
//关联一个Handler
public Messenger(Handler target)
//关联一个IBinder
public Messenger(IBinder target)
核心思路:
1.客户端与服务器都要有自己的Messenger并且关联一个Handler
2.服务端:将mServiceMessenger通过getBinder将IBinder传递给客户端
3.客户端:通过 public Messenger(IBinder target)构造方法获得服务器的mServiceMessenger,使用mServiceMessenger.send给服务器发送消息,并且在msg中把客户端的mClientMessenger带到服务器
4.服务端:服务器在Handler中接收到msg并且拿到客户端的mClientMessenger,使用mClientMessenger.send给客户端发送消息
客户端代码:
public class MainActivity extends Activity {
private static final int MSG_FROM_CLIENT = 0;
private static final int MSG_FROM_SERVICE = 1;
private ServiceConnection conn;
private Messenger mServiceMessenger;
private Button mButton;
//mClientHandler
private Handler mClientHandler = new Handler(){
public void handleMessage(Message msgFromService) {
switch (msgFromService.what) {
case MSG_FROM_SERVICE:
Log.i("zhangqi", "客户端:"+msgFromService.getData().getString("service_msg"));
break;
}
};
};
//mClientMessenger
private Messenger mClientMessenger = new Messenger(mClientHandler);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
Intent intent = new Intent(this,MyService.class);
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder iBinder) {
//拿到服务器传给客户端的IBinder,通过new Messenger(service)拿到mServiceMessenger
mServiceMessenger = new Messenger(iBinder);
//Messenger传递的是Message,实例化一个Message
Message msgFromClient = Message.obtain(null, MSG_FROM_CLIENT);
//Message传递的是Bundle
Bundle bundle = new Bundle();
//发送一个String类型的数据
bundle.putString("client_msg", "这里是客户端,呼叫服务器");
msgFromClient.setData(bundle);
//一定不要忘了将mClientMessenger带到服务器去
msgFromClient.replyTo = mClientMessenger;
try {
//调用mServiceMessenger.send将消息发送的服务器
mServiceMessenger.send(msgFromClient);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
//绑定Service
bindService(intent, conn, BIND_AUTO_CREATE);
//点击按钮发送客户端请求
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//由于在onServiceConnected中我们已经拿到了mServiceMessenger了,再发送消息的时候
//直接新建Message对象就可以了,最后调用mServiceMessenger将消息发送给服务器
Message msgFromClient = Message.obtain(null,MSG_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("client_msg", "客户端发起一次请求");
msgFromClient.setData(bundle);
msgFromClient.replyTo = mClientMessenger;
try {
mServiceMessenger.send(msgFromClient);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
//解绑Service
unbindService(conn);
conn = null;
}
}
服务端代码:
public class MyService extends Service{
private static final int MSG_FROM_CLIENT = 0;
private static final int MSG_FROM_SERVICE = 1;
// mServiceHandler
private Handler mServiceHandler = new Handler(){
public void handleMessage(android.os.Message msgFromClient) {
switch (msgFromClient.what) {
case MSG_FROM_CLIENT:
//拿到客户端发来的消息
Log.i("zhangqi", "服务器:"+msgFromClient.getData().getString("client_msg"));
//拿到客户端的mClientMessenger
Messenger mClientMessenger = msgFromClient.replyTo;
//Messenger传递的是Message,所以新建一个Message实例
Message msgFromService = Message.obtain(null,MSG_FROM_SERVICE);
//Message传递的是Bundle
Bundle bundle = new Bundle();
//发送一个String类型的数据
bundle.putString("service_msg", "这里是服务器,收到客户端请求");
msgFromService.setData(bundle);
try {
//调用mClientMessenger.send将消息发送给客户端
mClientMessenger.send(msgFromService);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
};
};
// mServiceMessenger关联mServiceHandler
private Messenger mServiceMessenger = new Messenger(mServiceHandler);
@Override
public IBinder onBind(Intent intent) {
//将IBinder传给客户端,客户端通过new Messenger(IBinder)拿到mServiceMessenger;
return mServiceMessenger.getBinder();
}
}
将服务端Service运行在单独的进程
在AndroidManifest.xml中注册Service并且指定android:process=”com.zhangqi.remote” 这样服务端Service就会运行在com.zhangqi.remote进程上,客户端运行在以包名命名的进程上
客户端发送一次请求,客户端就会回应: