转载请以链接形式标明出处: 本文出自:103style的博客
《Android开发艺术探索》 学习记录
目录
- 进程间通信简介
- Android中的多进程模式
- 如何开启多进程
- 多进程模式的运行机制
- 进程间通信基础概念介绍
- Serializable接口
- Parcelable接口
- 小结
进程间通信简介
进程间通信 即 IPC机制,IPC
全称为 Inter-Process Communication
。
首先我们先了解下什么是进程,什么是线程?
- 进程: 一般指一个执行单元。
PC的一个程序 或者 移动设备的一个应用
. - 线程:CPU调用的最小单元,是一种有限的系统资源。
一个进程可以包含多个线程。
IPC
不是 Android
独有的,任何一个操作系统都需要相应的 IPC
机制。比如:
- Windows上可以通过 剪切板、管道和邮槽来进行进程间通信。
- Linux 上可以 命令管道、共享内存、信号量等来进行进程间通信。
Android
是一种基于 Linux内核
的移动操作系统,它的进程间通信并不能完全继承 Linux
,它有自己的进程间通信方式,比如:Binder
、Socket
.
Android中的多进程模式
这里我们主要介绍两个问题:
- 如何开启开启多进程模式呢 ?
- 多进程的运行机制是怎样的呢 ?
如何开启开启多进程模式
那就是在 AndroidMainfest
文件中给 四大组件(Activity
、Service
、Receiver
、ContentProvider
) 指定 android:process
。
当然 我们也可以通过 JNI
在 native层
去 fork
一个进程。
示例:
代码语言:javascript复制<activity
android:name=".SecondActivity"
android:process=":second" />
<service
android:name=".TestService"
android:process="com.lxk.test.testService" />
<receiver
android:name=".TestReceiver"
android:process=":testService" />
<provider
android:name=".TestContentProvider"
android:authorities="lxk"
android:process=":testContentProvider" />
:xxx
写法 会在前面添加当前的应用包名, 并且该进程为当前应用的私有进程。
不用:xxx
写法的 TestService
则属于全局进程,其他应用可以通过 shareUID
方式和它跑在一个进程中。
运行程序,我们可以通过以下 shell 命令来查看.com.lxk.test 为包名
adb shell ps | grep com.lxk.test
多进程的运行机制
《Android开发艺术探索》的作者是这样形容多进程的——“当应用开启了多进程以后,各种奇怪的现象都出现了”。
原因是 Android为每一个进程都分配了一个独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,这会导致一个类的对象会在每一个上都有一个副本。
所以运行在不同进程中的四大组件,只要它们之间通过内存来共享数据,都会共享失败。
一般来说,使用多进程会出现以下问题:
- 静态成员和单例失效.
- 线程同步机制完全失效.
- SharedPreferences的可靠性降低.
- Application 会多次创建.
进程间通信基础概念介绍
这里我们是对 Serializable接口
、Parcelable接口
、Binder
的介绍。
Serializable接口
Serializable
是 Java 提供的一个序列化接口,是一个空接口,为对象提供标准的序列化和反序列化操作。
使用示例:
代码语言:javascript复制public class User implements Serializable {
public static final long serialVersionUID = 4516876541857684L;
public int userId;
public String name;
public int age;
}
我们只需要实现 Serializable
接口,其他的工作几乎都被系统自动完成了。
使用 ObjectOutputStream
和 ObjectInputStream
也可以轻松实现对象的序列化和反序列化。
String url = "cache.txt";
User user = new User(1,"lxk",25);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(url));
oos.writeObject(user);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(url));
User newUser = (User) ois.readObject();
ois.close();
我们注意到示例中有个 serialVersionUID
,它是用来做什么的呢?
serialVersionUID
一般是 IDE 根据当前类的结构自动生成的它的 hash值
,它并不是必须的。
它的作用主要是用来 区分序列化的内容对应的类的结构是否发生了变化,如果结构发生了变化,就会导致序列化失败,程序crash.
当我们不需要序列化某些字段的时候,我们可以用 transient
字段来修饰.
public class User implements Serializable {
public static final long serialVersionUID = 4516876541857684L;
public int userId;
public String name;
public int age;
public transient int temp;
}
Parcelable接口
Parcelable
是 Android
提供的序列化方式。
Parcelable
也是一个接口,我们只要实现这个接口,然后根据AndroidStudio
的提示重写对应方法。
public class User implements Parcelable {
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
public int userId;
public String name;
public int age;
protected User(Parcel in) {
userId = in.readInt();
name = in.readString();
age = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(userId);
dest.writeString(name);
dest.writeInt(age);
}
@Override
public int describeContents() {
return 0;
}
}
这里先说下,Parcel
内部包装了可序列化的数据,可以在 Binder
中自由传输。
通过以上示例代码,我们知道 序列化是由 writeToParcel
及 Parcel
的一系列 write
方法完成的,反序列化是由 CREATOR
及 Parcel
的一系列 read
方法完成的.
Parcelable
的方法说明:
方法 | 功能 | 标记位 |
---|---|---|
createFromParcel(Parcel in) | 从序列化后的对象中创建原始对象. | |
newArray(int size) | 创建指定长度的原始数据对象数组. | |
User(Parcel in) | 从序列化后的对象中创建原始对象. | |
writeToParcel(Parcel dest, int flags) | 将当前对象写入序列化结构中. flags包含右侧标记为的值. 1 表示 正在写入的对象是一个返回值,一些实现可能在此时释放资源. 2 表示父对象将负责管理名义上跨其内部数据成员复制的重复状态/数据. 几乎所有情况都是 0. | PARCELABLE_WRITE_RETURN_VALUE = 0x0001 PARCELABLE_ELIDE_DUPLICATES = 0x0002 |
describeContents() | 返回当前对象的内容描述. 1 表示包括文件描述符. 几乎所有情况都是 0. | CONTENTS_FILE_DESCRIPTOR = 0x0001 |
系统为我们提供了许多实现了 Parcelable
接口的类,它们都是可以直接序列化的。比如: Intent
、Bitmap
、Bundle
等,同时 List
、Map
也可以序列化。
Serializable 和 Parcelable对比
Serializable
是Java提供的序列化接口,使用起来简单但是开销大,需要大量的 I/O操作
。
Parcelable
是 Android提供的序列化接口,适合在Android平台,缺点就是使用起来相对麻烦点,但是效率高。
内存序列化 选 Parcelable
.
序列化到存储设备 或者 序列化之后进行网络传输 则选 Serializable
.
小结
- 介绍了通过在
AndroidMainfest
文件中给 四大组件指定android:process
即可指定不同的进程。 - 介绍了
Serializable
和Parcelable
接口的使用和优缺点,内存序列化 选Parcelable
,否则选Serializable
。
下一节 通过 AIDL 介绍 Binder 的工作机制。
如果觉得不错的话,请帮忙点个赞呗。
以上