跨进程通信Messenger和HandlerThread

来源:互联网 发布:手机徒步软件 编辑:程序博客网 时间:2024/06/04 23:30
进程间的通信首先想到的是AIDL,写AIDL文件实在是麻烦,维护起来也麻烦,不喜欢。
Messenger 也可以实现进程间通信的功能,看了一些牛人写的帖子,今天咱也学习和记录一下,便于以后查询。
参考 :
http://blog.csdn.net/h3c4lenovo/article/details/7915392
http://blog.csdn.net/lmj623565791/article/details/47079737

1、客户端通过绑定到服务端的server上获得服务端的Messenger对象,然后向服务端的server发送消息。(Messenger.send(Message))
2、客户端在向Server发送消息的同时把客户端的回调(Messenger对象)也带到服务端(msgFromClient.replyTo = mMessenger),

      待服务端计算完成后通过回调返回到客户端 : Messenger callBack = msgfromClient.replyTo ; callBack.send(msgToClient);

3、测试时跨进程 android:process=":MessengerService"

 其实这里内部也是依赖一个aidl生成的类,这个aidl位于:frameworks/base/core/java/android/os/IMessenger.aidl


Server这边还使用了HandlerThread类,顺便也学习一下。
HandlerThread也是一个Thread,只不过是帮我们封装了一下Looper,注意一下使用的顺序就可以了。
创建一个HandlerThread,即创建了一个包含Looper的线程。

HandlerThread handlerThread = new HandlerThread("work-thread");
handlerThread.start(); ,创建HandlerThread后一定要记得start()(Looper的使用啥的都是在HandlerThread的run()方法里面)
获取HandlerThread的Looper   Looper looper = handlerThread.getLooper();
创建Handler,通过Looper初始化   Handler handler = new Handler(looper);
通过以上三步我们就成功创建HandlerThread。通过handler发送消息,就会在子线程中执行。
如果想让HandlerThread退出,则需要调用handlerThread.quit();。


客户端代码:

package com.example.messengerservice;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.Messenger;import android.os.RemoteException;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.LinearLayout;import android.widget.TextView;import com.alibaba.fastjson.JSON;public class MainActivity extends Activity {private static final String TAG = "MessengerTest";private static final int MSG_OBJ = 0x111;private Button mBtnAdd;private LinearLayout mLyContainer;// 显示连接状态private TextView mTvState;private Messenger mService;private boolean isConn;private int i = 0;// 客户端的回调,传递到服务端用于返回服务端的计算结果  Message  msgFromClient.replyTo = mMessenger;private Messenger mMessenger = new Messenger(new Handler() {@Overridepublic void handleMessage(Message msgFromServer) {    // 接收Server端返回来的数据switch (msgFromServer.what) {case MSG_OBJ://UserInfo userInfo = (UserInfo)msgFromServer.obj;TextView tv = (TextView) mLyContainer.findViewById(msgFromServer.arg1);String strUserInfo = msgFromServer.getData().getString("UserInfo");UserInfo userInfo = JSON.parseObject(strUserInfo, UserInfo.class);tv.setText(tv.getText() + "=>" + msgFromServer.arg2 + ", userInfo = " + userInfo);break;}super.handleMessage(msgFromServer);}});private ServiceConnection mConn = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mService = new Messenger(service);   // 和服务端的Messenger建立关联isConn = true;mTvState.setText("connected!");}@Overridepublic void onServiceDisconnected(ComponentName name) {mService = null;isConn = false;mTvState.setText("disconnected!");}};private int mA;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final UserInfo userInfo = new UserInfo();userInfo.setAge(11);// 开始绑定服务bindServiceInvoked();mTvState = (TextView) findViewById(R.id.id_tv_callback);mBtnAdd = (Button) findViewById(R.id.id_btn_add);mLyContainer = (LinearLayout) findViewById(R.id.id_ll_container);mBtnAdd.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int pid = android.os.Process.myPid();Log.d(TAG, "MainActivity client pid = " + pid);try {int a = mA++;int b = (int) (Math.random() * 100);// 创建一个tv,添加到LinearLayout中TextView tv = new TextView(MainActivity.this);tv.setText(a + " + " + b + " = caculating ...");tv.setId(a);mLyContainer.addView(tv);i ++;userInfo.setName("name_" + i);String strUserInfo = JSON.toJSONString(userInfo);Log.d(TAG, "strUserInfo = " + strUserInfo);Message msgFromClient = Message.obtain(null, MSG_OBJ, a, b);Bundle bundle = new Bundle();  // 因为bundle实现了Parcelable接口。bundle.putString("UserInfo", strUserInfo);//msgFromClient.obj = strUserInfo;msgFromClient.setData(bundle);msgFromClient.replyTo = mMessenger;   //  设置回调if (isConn) {// 往服务端发送消息mService.send(msgFromClient);}}catch (RemoteException e) {e.printStackTrace();}}});}private void bindServiceInvoked() {Intent intent = new Intent();intent.setAction("com.zhy.aidl.calc");bindService(intent, mConn, Context.BIND_AUTO_CREATE);Log.e(TAG, "bindService invoked !");}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(mConn);}}

服务端代码:

package com.example.messengerservice;import android.app.Service;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.HandlerThread;import android.os.IBinder;import android.os.Message;import android.os.Messenger;import android.os.RemoteException;import android.util.Log;import com.alibaba.fastjson.JSON;public class MessengerService extends Service{private static final String TAG = "MessengerService";private static final int MSG_OBJ = 0x111;private HandlerThread mHandlerThread;private Handler mHandler;    private Messenger htMessenger;@Override/* mMessenger.getBinder()的实现 * public IBinder getBinder() {        return mTarget.asBinder();      } *  * mTarget是哪来的呢? mTarget是一个MessengerImpl对象,那么asBinder实际上是返回this,也就是MessengerImpl对象; */public IBinder onBind(Intent arg0) {return htMessenger.getBinder();}@Overridepublic void onCreate() {super.onCreate();// 和client端的PID不一样,说明运行在不同的进程中int pid = android.os.Process.myPid();Log.d(TAG, "onCreate() Server pid = " + pid);long threadId = Thread.currentThread().getId();Log.d(TAG, "onCreate() Server threadId = " + threadId);//生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,    //这个类由Android应用程序框架提供mHandlerThread = new HandlerThread("work-thread");//在使用HandlerThread的getLooper()方法之前,必须先调用该类的start();mHandlerThread.start();//即这个Handler是运行在mHandlerThread这个线程中mHandler = new Handler(mHandlerThread.getLooper()){@Overridepublic void handleMessage(Message msgfromClient) {//super.handleMessage(msgfromClient);if(msgfromClient.what != MSG_OBJ){return;}sendMsgToClient(msgfromClient);}};//htMessenger通过return htMessenger.getBinder()被客户端得到。    htMessenger = new Messenger(mHandler);} /** *  * @param msgfromClient */private void sendMsgToClient(Message msgfromClient){Message msgToClient = Message.obtain(msgfromClient);//返回给客户端的消息        //模拟耗时try {Thread.sleep(10000);msgToClient.arg2 = msgfromClient.arg1 + msgfromClient.arg2;Bundle bundle = msgfromClient.getData();String strUserInfo = bundle.getString("UserInfo");UserInfo userInfo = JSON.parseObject(strUserInfo, UserInfo.class);userInfo.setAge(userInfo.getAge() + 1);userInfo.setName(userInfo.getName() + "_from_server");bundle.putString("UserInfo", JSON.toJSONString(userInfo));msgToClient.setData(bundle);// 和onCreate()中的threadId不一样,说明运行在两个不同的线程中long threadId = Thread.currentThread().getId();Log.d(TAG, "htMessenger Server threadId = " + threadId);Messenger callBack = msgfromClient.replyTo; // 获得客户端的回调callBack.send(msgToClient); // 把信息发送到客户端}catch (InterruptedException e) {e.printStackTrace();}catch (RemoteException e) {e.printStackTrace();}}}


package com.example.messengerservice;import android.os.Parcel;import android.os.Parcelable;public class UserInfo implements Parcelable{private int age;private String name;/** * @return the age */public int getAge() {return age;}/** * @param age the age to set */public void setAge(int age) {this.age = age;}/** * @return the name */public String getName() {return name;}/** * @param name the name to set */public void setName(String name) {this.name = name;}/* (non-Javadoc) * @see java.lang.Object#toString() */@Overridepublic String toString() {return "UserInfo [age=" + age + ", name=" + name + "]";}@Overridepublic int describeContents() {// TODO Auto-generated method stubreturn 0;}@Overridepublic void writeToParcel(Parcel arg0, int arg1) {}}


activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/id_ll_container"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >    <TextView        android:id="@+id/id_tv_callback"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="Messenger Test!" />    <Button        android:id="@+id/id_btn_add"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="add" /></LinearLayout>


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.messengerservice"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="21" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name=".MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>         <service            android:name=".MessengerService"            android:process=":MessengerService"            android:enabled="true"            android:exported="true">            <intent-filter>                <action android:name="com.zhy.aidl.calc"></action>                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>        </service>    </application></manifest>



0 0
原创粉丝点击