IPC传递的都是序列化的数据(序列化和反序列化的核心思想是对象状态的保存和重建),序列化有两种,Parcelable、Serializable
知识点
- 同一个app如果有多个进程,每个进程会对应创建一个application对象,每一个系统都会单独分配一个虚拟机。进程间无法直接进行数据传递,需要通过aidl,binder,网络,文件共享等方式传递数据。静态成员和单例模式在不同进程间作用失效。
- 序列化
- Serializable或者Externalizable,非static和transient修饰的,核心类:ObjectOutputStream、ObjcetInputStream
- Parcelable,核心类:Parcel
- 网络传输:服务器将Java对象序列化为json/xml文件,文件以流的方式传输,客户端再将json/xml文件反序列化为对应语言的对象
- Binder
- AIDL(使用的对象必须是实现了Parcelable的类)
- 远程Service
- aidl:底层都是使用AIDL,用于不同进程的服务端和客户端通讯,可以处理多线程的进程间通讯
- Messenger:Messenger实现Parcelable接口,是一种封装好的AIDL,方便开发者进行跨进程通讯,主要用于不同进程的服务端和客户端的单线程通讯,不能处理多线程的进程间通讯
- 远程Service
Messenger使用demo
需要注意如果传递的是序列化对象,bundle.getXXX之前调用bundle.setClassLoader(getClass().getClassLoader()),不然会报错ClassNotFoundException,应用中存在两种类加载器它们分别是BootClassLoader和PathClassLoader。
<--清单文件配置-->
<--客户端,在app默认进程-->
<activity
android:name="com.hxx.arouter.messenger.TestMasengerClient"
android:label="@string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<--服务端,指定不同进程-->
<service android:name="com.hxx.arouter.messenger.TestMessengerService"
android:process=":school"/>
/**
* 客户端activity代码,1.绑定服务 2.创建handler,接收服务端消息
* 3.获取服务端的messenger 4.创建消息,messenger回复服务端消息
* 5.传递的消息类都是实现了Parcelable接口的
*/
public class TestMasengerClient extends Activity {
private TextView recieve;
private ServiceConnection serviceConnection;
private Messenger serviceMessenger;
private Messenger clientMassenger;
private Handler mHandler = new Handler(){
@Override public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
Bundle bundle = msg.getData();
// bundle.getXXX之前调用,不然会报错ClassNotFoundException,应用中存在两种类加载器它们分别是BootClassLoader和PathClassLoader.
bundle.setClassLoader(getClass().getClassLoader());
TeacherBean teacher = bundle.getParcelable("teacher");
String say = bundle.getString("say");
//服务端返回的消息
if (teacher != null){
Log.e("msg-client-接收消息", teacher.toString()+" >>> "+say);
recieve.setText("接收消息:"+teacher.toString()+" >>> "+say);
}
}
};
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_masenger);
TextView send = findViewById(R.id.send);
recieve = findViewById(R.id.recieve);
//1.绑定服务
Intent intent = new Intent();
intent.setClassName(this,"com.hxx.arouter.messenger.TestMessengerService");
serviceConnection = new ServiceConnection() {
@Override public void onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(TestMasengerClient.this, "bind success", Toast.LENGTH_SHORT).show();
//2.获取服务端的messenger,用于发消息
serviceMessenger = new Messenger(service);
}
@Override public void onServiceDisconnected(ComponentName name) {
Toast.makeText(TestMasengerClient.this, "Disconnected", Toast.LENGTH_SHORT).show();
serviceMessenger = null;
}
};
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
//创建客户端的messenger,发送给服务器端
clientMassenger = new Messenger(mHandler);
send.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
//2. 客户端发送消息 Messenger handler message
Message message = Message.obtain(null,1);
Bundle bundle = new Bundle();
StudentBean studentBean = new StudentBean("张三", "幼稚园");
String s_say = "我英语不好";
bundle.putParcelable("student", studentBean);
bundle.putString("say",s_say);
message.setData(bundle);
message.replyTo = clientMassenger;
try {
if (serviceMessenger != null){
serviceMessenger.send(message);
}
Log.e("msg-client-发送消息",studentBean.toString()+" >>> "+s_say);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override public void finish() {
super.finish();
unbindService(serviceConnection);
}
}
/**
* 1.继承service 2.创建handler 3.创建相应的Messenger,设置IBinder 4.接收客户端消息
* 5.回复客 户端消息
*/
public class TestMessengerService extends Service {
//1.创建handler
private Handler mHandler = new Handler(){
@Override public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
//收到客户端消息
// bundle.getXXX之前调用,不然会报错
Bundle data = msg.getData();
data.setClassLoader(getClass().getClassLoader());
String s_say = data.getString("say");
StudentBean student = data.getParcelable("student");
Toast.makeText(TestMessengerService.this, student.toString()+" >>> "+s_say, Toast.LENGTH_SHORT).show();
Log.e("msg-service-接收消息",student.toString()+" >>> "+s_say);
//给客户端发消息
Message serviceMsg = Message.obtain(null,2);
Bundle bundle = new Bundle();
TeacherBean teacherBean = new TeacherBean("王老师", "英语老师");
String t_say = "每天做英语阅读题";
bundle.putParcelable("teacher", teacherBean);
bundle.putString("say",t_say);
serviceMsg.setData(bundle);
Log.e("msg-service-发送消息",teacherBean.toString()+" >>> "+t_say);
try {
if (msg.replyTo != null){
msg.replyTo.send(serviceMsg);
}
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
};
//2.通过刚刚创建的Handler创建相应的Messenger
private final Messenger messenger = new Messenger(mHandler);
@Nullable @Override public IBinder onBind(Intent intent) {
//3.将设置binder
return messenger.getBinder();
}
}
<--简单布局-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<TextView
android:id="@+id/send"
android:text="客户端发送消息"
android:layout_marginTop="20dp"
android:background="@drawable/base_17c6cf_5"
android:textColor="#ffffff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="客户端接收消息"
android:layout_marginTop="20dp"
android:background="@drawable/base_ff7c29_5"
android:textColor="#ffffff"
android:layout_gravity="right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/recieve"
android:text="Msg:"
android:layout_marginLeft="25dp"
android:layout_marginTop="10dp"
android:textColor="#333333"
android:layout_gravity="right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>