深入剖析Android四大组件(四)——Messenger实现Android IPC

举报
择城终老 发表于 2021/07/26 23:10:20 2021/07/26
【摘要】 当Service不需要支持并发操作时Messenger会非常有用。Messenger类使用Handler执行每个传入的消息,所有客户端的调用都按顺序运行在同一个线程上,这和AIDL是有区别的,AIDL每个客户端对应一个线程。使用Messenger类还能避免AIDL文件带来的问题,并可以方便地为客户端提供异步消息API。虽然没有那么强大,但该类有时候会很有效,因为它更容易在客户...

当Service不需要支持并发操作时Messenger会非常有用。Messenger类使用Handler执行每个传入的消息,所有客户端的调用都按顺序运行在同一个线程上,这和AIDL是有区别的,AIDL每个客户端对应一个线程。使用Messenger类还能避免AIDL文件带来的问题,并可以方便地为客户端提供异步消息API。虽然没有那么强大,但该类有时候会很有效,因为它更容易在客户端和Service实现。

下面的例子展示了如何使用Messenger类来提供异步API。首先在onCreate()方法中创建Messenger,然后在onBind()方法中返回Binder对象。当Messenger接受到消息时,它使用存储在replyTo成员变量里的Messenger对象响应客户端的请求。

public class MessengerService extends Service { private Handler mMessageHandler;
 private Messenger mMessenger;
 public MessengerService() { } @Override
 public IBinder onBind(Intent intent) { return this.mMessenger.getBinder();
 } @Override
 public void onCreate() { super.onCreate();
 HandlerThread handlerThread=new HandlerThread("MessengerService");
 handlerThread.start();
 this.mMessageHandler=new Handler(handlerThread.getLooper(),new MyhandlerCallback());
 this.mMessenger=new Messenger(this.mMessageHandler);
 } @Override
 public void onDestroy() { super.onDestroy();
 this.mMessageHandler.getLooper().quit();
 } private class MyhandlerCallback implements Handler.Callback{ @Override
 public boolean handleMessage(Message msg) { boolean delivered=false;
 switch (msg.what){ case 0:
			//执行具体的任务	 delivered=true;
 break;
 case 1:
			//执行具体的任务 break;
 } Message reply=Message.obtain(null,2);//生成消息
 try { msg.replyTo.send(reply);//反馈给客户端
 } catch (RemoteException e) { e.printStackTrace();
 } return true;
 } }
}
    服务器端配置文件代码如下: <service
 android:name=".MessengerService"
 android:enabled="true"
 android:exported="true" > <intent-filter> <action android:name="com.example.liyuanjing.myapplication.MESSENGER_SERVICE"/> </intent-filter> </service>
下例中,客户端首先绑定到Service,然后使用IBinder作为参数构建一个Messenger对象,作为运行在远程Service中的Messenager的代理。当向Service发送消息时,也可以设置Message对象的replyTo属性。

public class MainActivity extends Activity implements ServiceConnection { private Button start;
 private Messenger mRemoteMessenger;
 private Messenger mReplyMessenger;
 private Handler mReplyHandler;
 @Override
 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 this.start=(Button)findViewById(R.id.start);
 HandlerThread handlerThread=new HandlerThread("ReplyMessenger");
 handlerThread.start();
 this.mReplyHandler=new Handler(handlerThread.getLooper(),new ReplyHandlerCallback());
 this.mReplyMessenger=new Messenger(this.mReplyHandler);
 } @Override
 protected void onResume() { super.onResume();
 bindService(new Intent("com.example.liyuanjing.myapplication.MESSENGER_SERVICE"),this,BIND_AUTO_CREATE);
 } @Override
 protected void onPause() { super.onPause();
 unbindService(this);
 } @Override
 protected void onDestroy() { super.onDestroy();
 this.mReplyHandler.getLooper().quit();
 } public void onSendTextPressed(View v){ Message message=Message.obtain();
 message.what=0;
 Bundle bundle=new Bundle();
 bundle.putInt("key",1);
 message.obj=bundle;
 message.replyTo=mReplyMessenger;
 try { mRemoteMessenger.send(message);
 } catch (RemoteException e) { e.printStackTrace();
 } } @Override
 public void onServiceConnected(ComponentName name, IBinder service) { this.mRemoteMessenger=new Messenger(service);
 this.start.setOnClickListener(new View.OnClickListener() { @Override
 public void onClick(View v) { onSendTextPressed(v);
 } });
 } @Override
 public void onServiceDisconnected(ComponentName name) { this.mRemoteMessenger=null;
 } private class ReplyHandlerCallback implements Handler.Callback{ @Override
 public boolean handleMessage(Message msg) { switch (msg.what){ case 2: Toast.makeText(MainActivity.this,"接受到了",Toast.LENGTH_LONG).show();
 break;
 } return true;
 } }
}
注意必须用Bundle传递常规类型数据,否则会报错:

java.lang.RuntimeException: Can't marshal non-Parcelable objects across processes.

因为Binder事务传递的数据被称为包裹(Parcel),必须实现Parcelable接口,否则无法在两个应用之间进行通信。之所以用Bundle传递是因为该类实现了Parcelable接口。当然如果要传递类也必须实现该接口。

文章来源: liyuanjinglyj.blog.csdn.net,作者:李元静,版权归原作者所有,如需转载,请联系作者。

原文链接:liyuanjinglyj.blog.csdn.net/article/details/45770241

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。