# 读 Android 开发艺术探索 &2
2017-02-06 11:26
519 查看
关键词:IPC / 多进程 / 序列化 / Binder
IPC,Inter-Process Communication 的缩写,含义为进程间通信或者跨进程通信,两个进程之间进行数据交换的过程。说到 IPC 的使用场景,就要提到多进程,当采用了多进程的设计方法,那么应用中就必须妥善处理进程间通信的各种问题。
[ 首先必须知道的几点:]
进程:一般是指一个执行单元,在 PC 和移动设备中指一个程序或者一个应用。
线程:CPU 调度的最小单元,是一种有限的系统资源。
一个进程可以包含多个线程,包含与被包含的关系。
一个进程可只有一个线程,主线程,在 Android 中就是 UI 线程,只有在 UI 线程里才能对界面元素进行操作。
ANR,Application Not Responding,应用无响应,防止ANR,把耗时的任务放在子线程中执行。
Android 有自己的进程间通信方式:Binder / Socket
通过系统提供的 ContentProvider 去查询数据的时候也是一种进程间通信,只不过通信细节被系统屏蔽了。
[ 需要知道以下几点:]
启动 SecondActivity 的时候系统会为它创建一个单独的进程:“io.github.isayes:remote”;
启动 ThirdActivity 的时候系统为它创建一个单独的进程:“io.github.isayes.remote”;
入口的 MainActivity 运行在默认的进程中,默认的进程名为包名;
进程名以 “:” 开头说明进程属于当前应用的私有进程(其它应用的组件不可以与之跑在同一个进程中),不以之开头的进程是全局进程(其它应用通过 ShareUID 方式与之可以跑在同一个进程中);
Android 系统会为每个应用分配一个唯一的 UID,UID 相同才能共享数据(data 目录、组件信息等私有数据);UID 相同并且签名相同才能跑在同一个进程中(还可以共享内存数据)。
Android 系统为每一个应用分配了一个独立的虚拟机,或者说为每一个进程都分配了一个独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,导致在不同的虚拟机中访问同一个类的对象会产生多份副本。一般来说,使用多线程会导致以下几个需要注意的问题 ↓
静态成员和单例模式失效
线程同步机制失效
SharedPreferences 的可靠性下降
Application 会多次创建(运行在同一个进程中的组件是属于同一个虚拟机和同一个 Application 的,同理,运行在不同的进程中的组件是属于不同的两个虚拟机和不同的 Application )
在多进程模式中,不同的进程的组件会有独立的虚拟机,独立的Application 以及内存空间;
理解同一个应用间的多进程:相当于两个不同的应用采用了 ShareUID 的模式。
为了解决多进程带来的问题,系统提供了很多跨进程通信的方法,虽然不能直接的共享内存,但是通过跨进程通信可以实现数据交互。实现跨进程通信的方式有:
1. 通过 Intent 传递数据
2. 共享文件
3. SharedPreferences
4. 基于 Binder 的 Messenger 和 AIDL
5. Socket 等
要理解 IPC 的各种方式,需要熟悉一些基础概念:序列化相关的 Serializable / Parcelable 接口 和 Binder
Serializable 和 Parcelable 接口完成对象的序列化过程,当我们通过 Intent 和 Binder 传输数据时就需要使用 Parcelable 或者 Serializable。
若需要把对象持久化到存储设备上或者通过网络传输给其他客户端,这时候也需要使用 Serializable 来完成对象的持久化。
【关于 Serializable 需要知道的几点】
Java 提供的序列化接口,是一个空接口
为对象提供标准的序列化和反序列化操作
几乎所有的工作都被系统自动完成了
静态成员变量属于类不属于对象,所以不会参与序列化过程
采用 transient 关键字标记的成员变量不参与序列化过程
serialVersionUID 辅助序列化和反序列化过程,序列化后的数据的 serialVersionUID 要和 当前类的 serialVersionUID 相等才能被正常地反序列化
【关于 Parcelable 需要知道的几点】
[ 对 Parcelable 的典型用法示例 ]
[ 对两种序列化接口的比较:]
【Binder】
需要知道的几点 ↓
Binder 是 Android 的一个实现了 IBinder 接口的类。
是 Android 的一种跨进程通信方式
是一种虚拟的物理设备,设备驱动是 /dev/binder
从 Android Framework 角度来看,Binder 是 ServiceManager 连接各种 Manager(ActivityManager、WindowManager 等等)和相应的 ManagerService 的桥梁。
从 Android 应用层来说,是客户端和服务端进行通信的媒介
Binder 主要用在 Service 中,包括 AIDL、Messenger(底层也是 AIDL)
所有可以在 Binder 中传输的接口都需要继承 IInterface 接口
关于 Binder 的知识需要单独总结一下:读 Android 开发艺术探索 &3 (番外篇之弄懂 Binder)
End.
Note by HF.
Learn from 《Android 开发艺术探索》
IPC,Inter-Process Communication 的缩写,含义为进程间通信或者跨进程通信,两个进程之间进行数据交换的过程。说到 IPC 的使用场景,就要提到多进程,当采用了多进程的设计方法,那么应用中就必须妥善处理进程间通信的各种问题。
[ 首先必须知道的几点:]
进程:一般是指一个执行单元,在 PC 和移动设备中指一个程序或者一个应用。
线程:CPU 调度的最小单元,是一种有限的系统资源。
一个进程可以包含多个线程,包含与被包含的关系。
一个进程可只有一个线程,主线程,在 Android 中就是 UI 线程,只有在 UI 线程里才能对界面元素进行操作。
ANR,Application Not Responding,应用无响应,防止ANR,把耗时的任务放在子线程中执行。
Android 有自己的进程间通信方式:Binder / Socket
通过系统提供的 ContentProvider 去查询数据的时候也是一种进程间通信,只不过通信细节被系统屏蔽了。
1. Android 中的多进程模式 #
在 Android 中使用多进程的常用方法只有一种:给四大组件在 AndroidManifest 中指定 android:process 属性。示例:<activity android:name="io.github.isayes.MainActivity" ... /> <activity android:name="io.github.isayes.SecondActivity" android:process=":remote" /> <activity android:name="io.github.isayes.ThirdActivity" android:process="io.github.isayes.remote" />
[ 需要知道以下几点:]
启动 SecondActivity 的时候系统会为它创建一个单独的进程:“io.github.isayes:remote”;
启动 ThirdActivity 的时候系统为它创建一个单独的进程:“io.github.isayes.remote”;
入口的 MainActivity 运行在默认的进程中,默认的进程名为包名;
进程名以 “:” 开头说明进程属于当前应用的私有进程(其它应用的组件不可以与之跑在同一个进程中),不以之开头的进程是全局进程(其它应用通过 ShareUID 方式与之可以跑在同一个进程中);
Android 系统会为每个应用分配一个唯一的 UID,UID 相同才能共享数据(data 目录、组件信息等私有数据);UID 相同并且签名相同才能跑在同一个进程中(还可以共享内存数据)。
Android 系统为每一个应用分配了一个独立的虚拟机,或者说为每一个进程都分配了一个独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,导致在不同的虚拟机中访问同一个类的对象会产生多份副本。一般来说,使用多线程会导致以下几个需要注意的问题 ↓
静态成员和单例模式失效
线程同步机制失效
SharedPreferences 的可靠性下降
Application 会多次创建(运行在同一个进程中的组件是属于同一个虚拟机和同一个 Application 的,同理,运行在不同的进程中的组件是属于不同的两个虚拟机和不同的 Application )
在多进程模式中,不同的进程的组件会有独立的虚拟机,独立的Application 以及内存空间;
理解同一个应用间的多进程:相当于两个不同的应用采用了 ShareUID 的模式。
为了解决多进程带来的问题,系统提供了很多跨进程通信的方法,虽然不能直接的共享内存,但是通过跨进程通信可以实现数据交互。实现跨进程通信的方式有:
1. 通过 Intent 传递数据
2. 共享文件
3. SharedPreferences
4. 基于 Binder 的 Messenger 和 AIDL
5. Socket 等
要理解 IPC 的各种方式,需要熟悉一些基础概念:序列化相关的 Serializable / Parcelable 接口 和 Binder
2. IPC 基础 相关概念 #
IPC 的基础概念有三点: |
---|
Serializable |
Parcelable |
Binder |
若需要把对象持久化到存储设备上或者通过网络传输给其他客户端,这时候也需要使用 Serializable 来完成对象的持久化。
【关于 Serializable 需要知道的几点】
Java 提供的序列化接口,是一个空接口
为对象提供标准的序列化和反序列化操作
几乎所有的工作都被系统自动完成了
静态成员变量属于类不属于对象,所以不会参与序列化过程
采用 transient 关键字标记的成员变量不参与序列化过程
private static final long serialVersionUID = -1589804003600796026L;
serialVersionUID 辅助序列化和反序列化过程,序列化后的数据的 serialVersionUID 要和 当前类的 serialVersionUID 相等才能被正常地反序列化
【关于 Parcelable 需要知道的几点】
方法 / 功能 / 标记位 |
---|
createFromParcel(Parcel in) / 从序列化后的对象中创建原始对象 / |
newArray(int size) / 创建指定长度的原始对象数组 / |
User(Parcel in) / 从序列化后的对象中创建原始对象 / |
writeToParcel(Parcel out, int flags) / 将当前对象写入序列化结构中,其中 flags 标识有两种值:0 或 1,为 1 时标识当前对象需要作为返回值返回,不能立即释放资源,几乎所有情况都为 0 / PARCELABLE_WRITE_RETURN_VALUE |
describeContents / 返回当前对象的内容描述。如果含有文件描述符,返回 1,否则返回 0, 几乎所有情况都返回 0 / CONTENTS_FILE_DESCRIPTOR |
public class User implements Parcelable{ public int userId; public String userName; public boolean isMale; public Book book; public User(int userId, String userName, boolean isMale){ this.userId = userId; this.userName = userName; this.isMale = isMale; } // 内容描述功能 public int describeContents(){ return 0; } // 序列化功能的完成,最终通过 Pacel 中的一系列 write 方法来完成 public void writeToParcel(Parcel out, int flags){ out.wirteInt(userId); out.writeString(userName); out.writeInt(isMale ? 1 : 0); out.writeOarcelable(book, 0); } // 反序列化功能的完成 public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() { public User createFromParcel(Parcel in) { return new User(in); } public User[] newArray(int size){ return new User[size]; } }; private User(Parcel in){ userId = in.readInt(); userName = in.readString(); isMale = in.readInt() == 1; book = in.readParcelable(Thread.currentThread().getContextClass-Loader()); } }
[ 对两种序列化接口的比较:]
Serializable / Parcelable |
---|
Serializable 是 Java 提供的序列化接口 / Parcelable 是 Android 提供的序列化接口,更适合在 Android 平台上 |
Serializable 使用简单但是开销大,序列化和反序列化过程中需要大量的 IO 操作 / Parcelable 使用麻烦但是效率很高 |
需要知道的几点 ↓
Binder 是 Android 的一个实现了 IBinder 接口的类。
是 Android 的一种跨进程通信方式
是一种虚拟的物理设备,设备驱动是 /dev/binder
从 Android Framework 角度来看,Binder 是 ServiceManager 连接各种 Manager(ActivityManager、WindowManager 等等)和相应的 ManagerService 的桥梁。
从 Android 应用层来说,是客户端和服务端进行通信的媒介
Binder 主要用在 Service 中,包括 AIDL、Messenger(底层也是 AIDL)
所有可以在 Binder 中传输的接口都需要继承 IInterface 接口
关于 Binder 的知识需要单独总结一下:读 Android 开发艺术探索 &3 (番外篇之弄懂 Binder)
End.
Note by HF.
Learn from 《Android 开发艺术探索》
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件