跨进程通信Messenger和HandlerThread
2015-08-13 15:30
295 查看
进程间的通信首先想到的是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();。
客户端代码:
服务端代码:
activity_main.xml
AndroidManifest.xml
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() { @Override public 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() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = new Messenger(service); // 和服务端的Messenger建立关联 isConn = true; mTvState.setText("connected!"); } @Override public void onServiceDisconnected(ComponentName name) { mService = null; isConn = false; mTvState.setText("disconnected!"); } }; private int mA; @Override protected 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() { @Override public 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 !"); } @Override protected 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(); } @Override public 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()){ @Override public 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() */ @Override public String toString() { return "UserInfo [age=" + age + ", name=" + name + "]"; } @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public 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>
相关文章推荐
- JavaScript生成SQL查询表单的方法
- onedrive实现excel在线编辑 online excel
- 小孩子学编程
- C++ 多态性的理解
- 栈的应用->中缀转后缀
- Linux学习记录(2)安装Linux系统以及VirtualBox增强工具
- c3p0
- CALayer # 03 # view 的显示过程
- P31RestKit.dll 2.0 Unity3d json
- UISwitch——开关控件
- Low cost diesel-engined wristwatches despite the fact that invest in whatever you idea seemed to be a legitimate dealership inside of a shopping mall
- 闭包问题
- 100条超实用微信营销技巧:公众号、朋友圈和微信营销
- 九度oj 1024
- 100条超实用微信营销技巧:公众号、朋友圈和微信营销
- JS小测
- hdu 2602Bone Collector
- LeetCode-Min Stack
- iOS中UDP的使用
- jquery ajax请求后台 的简单例子