1、IPC 是 Inter-Process Communication 的缩写,含义为 进程间通信 或者 跨进程通信,指 两个进程之间进行数据交换的过程。
2、操作系统描述:
1)线程是 CPU 调度的最小单元,同时 线程是 一种有限的 系统资源。
2)进程 一般 指一个执行单元,在 PC和移动设备上 指 一个程序或者 一个应用。
3)一个 进程 可以 包含多个 线程。因此 进程和线程是 包含与被包含的关系。
3、在 Android里面 主线程 也叫 UI线程,在 UI 线程中 才能操作 界面元素。
4、在Android中 有特色的 进程间通信方式 就是 Binder;Android 还支持 Socket,通过Socket 也可以实现 任意两个终端之间的通信,一个 设备上 两个进程通过 Socket 通信也是可以的。
2.2.1 开启多进程模式
1、开启多线程方法:
1)常规方法: 给 四大组件(Activity、Service、Receiver、ContentProvider) 在AndroidMenifest 中 指定 android:process属性。
2)非常归方法:通过JNI 在native层 去 fork 一个新的 进程。(属特殊情况,也不是 常用的创建多进程的方式)
2、示例:
1)可以用 shell 命令 查看 进程信息。
adb shell ps 或者 adb shell ps|grep 包名(利 com.ryg.chapter_2)
3、android:process=":remote"
android:process="com.ryg.chapter_2:remote"
两种方式区别:
① 进程以":"开头,默认前面附加上 当前的包名;属于 当前应用的 私有进程,其他的应用组件 不可以 和它 跑在 同一个进程中。
②进程不以":"开头,是一种 完整 的命名方式,不附加包名信息; 属于 全局进程,其他应用 通过 ShareUID 方式 可以和 它 跑在同一个进程中。
4、Android 系统会为每个应用分配 一个 唯一的UID,具有 相同 的UID 的应用才能共享数据。
两个应用通过 ShareUID 跑在同一个进程中 要求:两个应用 有 相同的 ShareUID并且 签名相同。
可以互相访问对方的私有数据,比如data目录,组件信息等,不管是否跑在同一进程中。
如果在同一进程,还可以 共享 内存数据。 【他们看起来 就像是 一个应用 的两个部分】
2.2.2 多进程模式的运行机制
1、Android为 每一个应用分配了一个独立的虚拟机,或者说 为每个进程 都分配 一个独立的虚拟机,不同的虚拟机 在内存 分配上有不同的地址空间, 导致 在 不同的虚拟机中 访问 同一个类 的对象 会 产生 多份副本。【在一个进程中 修改某个值,只会影响当前进程,对其他进程不会造成任何影响。】
2、使用 多进程 造成的问题:
1)静态成员 和 单例模式 完全失效;
2)线程同步机制 完全失效;
3)SharePreferences 的可靠性 下降;【原因: SharePreferences 不支持两个进程 同时 去执行 写操作----SharePreferences 底层 是通过 读/写 XML文件 来实现,并发写 可能出现问题】
4)Application 会多次创建。【不同进程的组件 拥有独立的 虚拟机、 Application】
3、跨进程通信 实现 数据交互
1)通过 Intent 来传递数据;
2)共享文件 和 SharePreferences;
3)基于 Binder 的 Messenger和AIDL;
4)Socket等。
2.3.1 Serializable接口
Serializable 是Java 提供的 一个 序列化接口,一个空接口,为 对象 提供 标准的 序列化 和 反序列化操作。
1)使用方式: 在类中 声明 标识,如下所示。
private static final long serialVersionUID=xxxxxxxL;
PS:
① serialVersionUID不是必须,不声明仍可以实现 序列化,但是会对 反序列化过程产生影响(?)
② serialVersionUID 是用来 辅助 序列化和 反序列化过程的,原则上 序列化后 的数据中 的serialVersionUID 只有 和当前类的 serialVersionUID 相同才能够 正常的被反序列化。
③ serialVersionUID的详细工作机制:
序列化的时候,系统会把当前类的 serialVersionUID 写入序列化的文件(也可能是其他中介)中,当 反序列化的时候,系统会去检测 文件中 的serialVersionUID,看他是否和当前类的 serialVersionUID 一直,如果一致,说明 序列化的类的版本 和当前类的版本是相同的,可以成功反序列化,否则无法正常反序列化。
④ 重点注意:首先静态成员变量属于类不属于对象,所以不会参与序列化过程;其次用 transient关键字标记的成员变量不参与序列化过程。
⑤方法:
private void writeObject(java.io.ObjectOutputStream out) throws IOException{
//write 'this' to 'out' ...
}
private void readObject(java.io.ObjectInputStream out) throws IOException,ClassNotFoundException{
//populate the fields of 'this' from the data in 'in' ...
2.3.2 Parcelable接口
1)是Android 中提供新的序列化方式。【一个类的对象就可以实现序列化并可以通过Intent和Binder传递】
2)三大过程:序列化,反序列化,内容描述。
①序列化:writeToParcel方法完成,最终是 通过 Parcel中的一系列 write 方法来完成。
②反序列化:由CREATOR来完成,其内部表明了如何创建序列化对象和数组,并通过Parcel的一系列read方法来完成反序列化过程;
③内容秒速:describeContents方法完成;几乎在所有情况下这个方法都应该返回0,仅当当前对象中存在文件描述符时,此方法返回1。
3)Parcelable、Serializable 如何选取?
①Serializable 是Java中的序列化接口,用起来简单但是 开销很大,徐泪花和反序列化过程 需要大量 I/O操作。
②Parcelable数 Android中的序列化方式,更适合在Android平台上。缺点是 使用起来稍微麻烦点,但是效率很高,是Android推荐的序列化方式。【首选Pracel】
③将对象序列化到存储设备中 或者 将对象 序列化后通过 网络传输时 ,建议使用 Serializable【Pracel 也是可以】。
【后续追加】