跨进程通信基础篇
含义:
跨进程通信,是指两个进程之间数据交换的过程,英文全称 Inter-Process Communication 缩写IPC
进程和线程的关系:
在移动设备上,一个程序或者一个应用,就是一个进程,一个进程里面可以包含多个线程
(例如:一个应用里面有一个主线程(用于更新UI)和多个子线程(执行耗时的任务))
开启多线程的方法:
在Android中开启多进程只有一种方法: 那就是给4大组件(Activity,Service,Receiver,ContentProvider)在Menifest中指定android:process属性,除此之外没有其他的方法(通过JNI在native层去fork一个新进程除外)
实例1如下:
<activity
android:name=".activity.Main2Activity"
android:process=":remote1" />
实例2如下:
<activity
android:name=".activity.Main3Activity"
android:process="com.hlj.demo.remote2" />
说明:
1.首先实例1中 ":“的含义是指:这是一种简写
a.当前的进程名称前面要附加上当前的包名 进程完整名称:com.hlj.demo:remote1
b.以”:"开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中
2,实例2中的进程名称是一种完整的命名方式,不会附加包名信息,其次它属于全局进程,其他应用通过ShareUID方式可以和它跑在同一个进程中.(2个应用的签名也要相同)
注意:
程序入口MainActivity,默认没有给它process属性,那么它就运行在默认的进程中,默认的进程名称是包名,如果给它指定了process属性,那么它就运行在该指定进程当中
如何查看自己开启了多少个进程呢,studio如下图所示:

运行在同一个进程中的组件是属于同一个虚拟机和同一个Application,可以共享Applicaiton下的数据,运行在不同进程中的组件是属于2个不同的虚拟机和2个不同的Application,2个不同的Application数据是不能互通的
IPC的基础概念: Serializable接口,Parcelable接口,Binder
Serializable接口:Serializable是java所提供的一个序列化的接口,它是一个空接口,为对象提供序列化和反序列化操作
//实现Serializable接口即可
public class UserBean implements Serializable{
private static final long serialVersionUID=1L;
public String name;
}
UserBean user = new UserBean();
user.name = "hao123";
if (!StrUtils.IsKong(Environment.getExternalStorageDirectory() + "/" + "demo")) {
String baseExternalStoragepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "demo";
baseDirectory = new File(baseExternalStoragepath);
if (!baseDirectory.exists()) {
//先创建文件夹
baseDirectory.mkdirs();
}
//再创建文件
File wejian = new File(baseDirectory.getPath() + "/" + "user.txt");
if (!wejian.exists()) {
wejian.createNewFile();
}
//序列化到文件中
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(wejian));
out.writeObject(user);
out.flush();
out.close();
}
//反序列化,从文件中读取文件
File wejian=new File(baseDirectory.getPath()+"/"+"user.txt");
ObjectInputStream in=new ObjectInputStream(new FileInputStream(wejian));
UserBean user=(UserBean)in.readObject();
in.close();
注意:
序列化和反序列化需要读写文件,所以需要在清单文件配置读写权限,大于6.0的设备还要动态申请权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
serialVersionUID:
一般来说我们应该手动指定serialVersionUID的值,这样做的好处是:当版本升级后,我们可能删除了某个成员变量也可能增加了一些新的成员变量,但指定了这个值以后,反序列化还是可以成功,程序可以最大限度的恢复数据,如果不指定serialVersionUID的值的话,程序会挂掉,但是如果类结构发生了非常规性的改变,例如修改了成员变量的类型结构,这种毁灭性的改变后,反序列化还是会失败,因为无法从老版本的数据中还原一个新的类型结构的对象
注意:
1,静态成员属于类不属于对象,所以不会参与序列化的过程
2,用transient关键字标记的成员变量不会参与序列化的过程
Parcelable接口
Parcelable 是android中提供的新的序列化方式,只要实现这个接口,一个类的对象就可以实现序列化,并且可以通过Intent和Binder传输
实例如下:
public class User2 implements Parcelable {
public int age;
//体重
public int weight;
public String name;
public Book book;
public User2(){
}
public User2(Parcel in) {
//注意:这里读取字段的属性要和写入字段的顺序一样 age,weight,name,book
age=in.readInt();
weight=in.readInt();
name=in.readString();
//由于book是另一个序列化对象,所以它的反序列化的过程要传递当前上下文类加载器
book= in.readParcelable(Thread.currentThread().getContextClassLoader());
}
//studio会自动生成这里
public static final Creator<User2> CREATOR = new Creator<User2>() {
@Override
public User2 createFromParcel(Parcel in) {
return new User2(in);
}
@Override
public User2[] newArray(int size) {
return new User2[size];
}
};
//studio会自动生成这里
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeInt(weight);
dest.writeString(name);
dest.writeParcelable(book,0);
}
}
说明:
1,从Parcel in里面读取字段的顺序一定要和writeToParcel字段的顺序一样(否则同一个类型的字段例如age和weight数据会搞混)
2,由于Book是另一个序列化对象,所以它的反序列化的过程要传递当前上下文类加载器
Parcelable接口和Serializable接口的比较
共同点:都能实现序列化并且都可用于Intent间的数据传递
不同点:Serializable是java中提供的接口,使用起来更加简单,但是开销很大,需要大量的IO操作,Parcelable是android中的序列化方式,所以更适用与android平台,缺点是使用起来稍微麻烦一点,优点是效率高
Binder:
直观来讲,Binder是android中的一个类,它实现了IBinder接口.从IPC的角度来讲,Binder是Android中的一种跨进程通信方式,从AndroidFramework角度来讲,Binder是ServiceManager连接各种Manager(ActivityNamager,WindowManger等等)的桥梁;从Android应用层来讲,Binder是客户端和服务端进行通信的媒介,当binderService的时候,服务端会返回一个包含服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包含普通的服务和基于AIDL的服务,普通的service服务不涉及进程间通信,主要是AIDL会涉及binder的核心
结尾:
下一篇会总结跨进程通信的几种方式,尽情期待啦~^^