黑马程序员技术交流社区
标题: 跨进程通信:Messenger信使 [打印本页]
作者: 黄健 时间: 2015-12-28 14:30
标题: 跨进程通信:Messenger信使
本帖最后由 黄健 于 2015-12-28 14:29 编辑
跨进程通信:Messenger信使
在Android开发中,经常会涉及到Activity与Service互相交互的场景,Activity作为应用的前台交互界面,Service作为应用的后台服务,当用户触摸了交互界面时,Activity去请求Service做业务操作,Service根据Activity发来的请求做出相应的业务逻辑操作,如:访问网络、播放音乐、操作文件等,然后再把处理的结果返回给Activity,这时Activity拿到响应结果去更新界面,最终反馈给用户。实现Activity与Service交互的方法有多种,这里就介绍一下怎么使用Messenger进行Activity与Service互相交互。
使用Messenger进行Activity与Service互相交互
先来看一下Messenger类:Messenger创建时拥有一个消息处理器(Handler),Messenger可以发送消息,也可以处理消息,当使用Messenger发送消息后,它自己的消息处理器就接收到消息并进行处理。
那么,使用Messenger进行Activity与Service交互的实现机制就是:Activity和Service都创建一个Messenger对象,然后把自己的Messenger对象传递给对方,接着Activity和Service就可以拿对方传递过来的Messenger对象给对方发送消息,然后在Messenger的消息处理器里面处理对方使用自己的Messenger对象发过来的消息。
接下来,就可以用代码一步步去实现了。既然是Activity与Service交互,那就首先需要Activity与Service这两个组件。
第1步:创建Service类,命名MessageService继承Service。
public class MessengerServiceextends Service{
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
第2步:Activity要想和Service交互,必须让Activity绑定Service,所以要实现Service的onBind方法,为了把自己的Messenger对象传递给Activity,在onBind方法里面返回自己的Messenger的IBinder对象。
// 创建Messenger对象,并给传递一个处理消息的Handler
private final MessengermMessenger = new Messenger(new ServiceIncomingHandler());
@Override
public IBinder onBind(Intentintent) {
return mMessenger.getBinder();// 把Messenger的IBinder对象返回给Activity
}
// 用来处理Activity发过来的Message
private class ServiceIncomingHandlerextends Handler {
@Override
public void handleMessage(Message msg) {
}
}
第3步:创建Activity,并绑定MessageService,绑定成功后,拿到MessageService返回来的IBinder对象生成Messenger对象,同时再创建一个自己的Messenger对象,并把自己的Messenger发送给MessageService。此时Activity已经可以给Service发送消息了。
public classMessengerActivity extends Activity {
// 从MessageService返回来的Messenger
private Messenger mService;
// 自己的Messenger
private final Messenger mMessenger = newMessenger(new ActivityIncomingHandler());
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 绑定Service,为了拿到Service中的Messenger
bindService(new Intent(this,MessengerService.class), mConnection,Context.BIND_AUTO_CREATE);
}
private ServiceConnection mConnection = newServiceConnection() {
public voidonServiceConnected(ComponentName className, IBinder service) {
// 用Service返回来的IBinder生成Messenger,相当于拿到Service的Messenger
// 用来给Service发送消息
mService = new Messenger(service);
Message msg =Message.obtain(null,MessageConstant.MSG_REGISTER_CLIENT);
// 把自己的Messenger发送给Service,以便Service拿着给我发消息
msg.replyTo = mMessenger;
mService.send(msg);
}
public voidonServiceDisconnected(ComponentName className) {
mService = null;
}
};
private class ActivityIncomingHandlerextends Handler {
@Override
public void handleMessage(Message msg){
}
}
}
第4步:在第3步中,MessengerActivity已经把它的Messenger赋值给msg.replyTo并且发过来,接着就可以在MessageService的消息处理器中,把MessengerActivity发过来的Messenger取出来并保存。此时Service也可以给Activity发送消息了。
// Service可以被多个Activity绑定,用来记录所有Activity发过来的Messenger
privateArrayList<Messenger> mClients = new ArrayList<Messenger>();
private classServiceIncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
caseMessageConstant.MSG_REGISTER_CLIENT:
mClients.add(messenger);// 保存Activity发送过来的Messenger
break;
}
}
}
第5步:Activity与Service通过Messenger互相发送消息,根据Message的what值来判断消息类型。为了统一管理消息类型,把所有消息的what值放在常量类MessageConstant里。
public class MessageConstant{
public static final int MSG_REGISTER_CLIENT= 1;
public static final intMSG_REQUEST_SERVICE_LOGIN = 3;// 请求登录
public static final intMSG_RESPONSE_CLIETN_LOGINOK = 4;// 登录成功
}
------------------------------------分割线-----------------------------------------
MessengerActivity.java 代码片段:
// 点击登录按钮时,给Service发送消息让它去访问服务器
public void login(View v){
sendMessageToService(Message.obtain(null,MessageConstant.MSG_REQUEST_SERVICE_LOGIN));
}
private void sendMessageToService(Messagemsg) {
try {
mService.send(msg);
} catch (RemoteException e) {
}
}
private classActivityIncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
caseMessageConstant.MSG_RESPONSE_CLIETN_LOGINOK:
// 处理服务器返回来的登录成功消息
Toast.makeText(getApplicationContext(),"登录成功", 0).show();
break;
}
}
}
------------------------------------分割线-----------------------------------------
MessageService.java 代码片段:
private classServiceIncomingHandler extends Handler {
@Override
public void handleMessage(Message msg){
switch (msg.what) {
caseMessageConstant.MSG_REGISTER_CLIENT:
mClients.add(messenger);// 保存Activity发送过来的Messenger
caseMessageConstant.MSG_REQUEST_SERVICE_LOGIN:
// 处理登录业务
login(msg);
break;
}
}
}
private void login(Messagemsg) {
// 开启线程,访问服务器
...
// 给Activity发送登录成功的消息,让Activity更新界面sendMessageToAllClient(Message.obtain(null,MessageConstant.MSG_RESPONSE_CLIETN_LOGINOK));
}
// 给Activity发送消息的方法
private voidsendMessageToAllClient(Message message) {
// 给所有的cliet发送响应消息
for (int i = 0; i < mClients.size();i++) {
mClients.get(i).send(Message.obtain(message));
}
}
}
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |