跨进程通信Messenger和HandlerThread
来源:互联网 发布:手机徒步软件 编辑:程序博客网 时间:2024/06/04 23:30
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>
- 跨进程通信Messenger和HandlerThread
- Messenger 跨进程通信
- android Messenger 跨进程通信
- android Messenger 跨进程通信
- Android Messenger 跨进程通信!!!!!!!!!!!!!!!!!!
- Android Messenger 跨进程通信
- 【Android】Messenger 跨进程通信
- Android Messenger 跨进程通信
- Android Messenger 跨进程通信
- Android 跨进程通信--Messenger
- 利用Messenger跨进程通信
- 跨进程通信之Messenger
- Messenger实现跨进程通信
- android Messenger跨进程通信
- Messenger:使用消息的跨进程通信
- Messenger:使用消息的跨进程通信
- Messenger:使用消息的跨进程通信
- Messenger:使用消息的跨进程通信
- onedrive实现excel在线编辑 online excel
- Linux学习笔记----文件处理命令----touch ---创建文件
- 简单的Stack
- java通过JDBC链接SQLServer2012
- 飞思卡尔 imx6 GC0308 摄像头驱动配置调试过程
- 跨进程通信Messenger和HandlerThread
- git代理设置
- 解决vlc播放UDP发送的RTP封装H.264码流
- 首页对应的模板,以及对应的类
- MKNetworkKit 使用
- leetcode 132 —— Palindrome Partitioning II
- android 处理按键动作
- JSP JDBC 连接 SqlServer2008
- Visual C#2010学习笔记六之运算符的重载