A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黄健 黑马帝   /  2015-12-28 14:30  /  1497 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 黄健 于 2015-12-28 14:29 编辑

跨进程通信:Messenger信使

在Android开发中,经常会涉及到Activity与Service互相交互的场景,Activity作为应用的前台交互界面,Service作为应用的后台服务,当用户触摸了交互界面时,Activity去请求Service做业务操作,Service根据Activity发来的请求做出相应的业务逻辑操作,如:访问网络、播放音乐、操作文件等,然后再把处理的结果返回给Activity,这时Activity拿到响应结果去更新界面,最终反馈给用户。实现Activity与Service交互的方法有多种,这里就介绍一下怎么使用Messenger进行Activity与Service互相交互。

使用Messenger进行ActivityService互相交互
先来看一下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));
        }
    }
}


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马