《Android开发艺术探索》读书笔记--part2 IPC进程间通信机制

IPC:Inter-Process Communication,进程间通信或跨进程通信
  • part2-1 线程与进程
    一个应用程序对应一个进程,一个进程最少由一个线程(主线程)组成,线程是CUP调度的最小单位
  • part2-2 Android中的多进程
    Android四大组件可以通过android:process=”“属性来开启多进程
    • Get:
      • 可通过android:process=”:remote”或android:process=”自定义进程名”配置多进程,进程名一般指定当前包名+后缀(自定义)。其中:remote为当前包名+:remote的缩写,属于当前应用的私有进程,其他应用的组件不可以跑进这个进程;自定义进程名开启的为全局进程,其他应用通过ShareUID方法可以和它跑在同一个进程中。
      • 使用多进程会带来几个问题:
        • 静态成员和单例模式完全失效
        • 线程同步机制完全失效
        • SharePreference可靠性下降
        • Application会多次创建
  • part2-3 IPC基础
    如果一个对象想通过Intent和Binder传递,该对象需要序列化,可通过Serializable接口或Parcelable接口实现序列化。
    • Get:
      • Serializable
        使用Serializable接口序列化时,通过指定一个serialVersionUID可以更好的实现反序列化;如果没有指定serialVersionUID,当对象的成员发生改变时,反序列化会失败。
      • Parcelable (借用书中例子:一个典型的实现了Parcelable 接口的对象类)
public class Book implements Parcelable { public int bookId; public String bookName; public Book() { }public Book(int bookId, String bookName) { this.bookId = bookId; this.bookName = bookName; }//“内容描述”,如果含有文件描述符返回1,否则返回0,几乎所有情况下都是返回0 public int describeContents() { return 0; }//实现序列化操作,flags标识只有0和1,1表示标识当前对象需要作为返回值返回,不能立即释放资源,几乎所有情况都为0 public void writeToParcel(Parcel out, int flags) { out.writeInt(bookId); out.writeString(bookName); }//实现反序列化操作 public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { //从序列化后的对象中创建原始对象 public Book createFromParcel(Parcel in) { return new Book(in); } public Book[] newArray(int size) {//创建指定长度的原始对象数组 return new Book[size]; } }; private Book(Parcel in) { bookId = in.readInt(); bookName = in.readString(); }}

  • 对比
    Serializable是Java提供的接口,使用简单,但开销大,需进行大量I/O操作;Parcelable是Android中的序列化方式,使用麻烦,但效率高,是Android推荐使用的方式。但由于其过程复杂,我们更多使用的是Serializable。
intent().putExtra(String name, Serializable value) intent().putExtra(String name, Parcelable value) getIntent().getSerializableExtra(name); getIntent().getParcelableExtra(name);

  • Binder机制((难理解,详见原书,引用书中对Binder的直观描述)
    • Binder是Android中的一个类,它实现了IBinder接口。从IPC角度看,Binder是Android中一种跨进程通信的方式;Binder还可以理解为虚拟的物理设备,它的设备驱动是/dev/binder;从Framework层角度看,Binder是ServiceManager连接各种Manager和相应的ManagerService的桥梁;从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。
  • Android中的IPC方式
    • Bundle
      实际开发中我们最常使用的传递数据方式,其通过了Map的key+vaule形式保存数据。Activity、Service、BrocastReviever都支持使用Intent传递Bundle数据,Bundle支持的类型有:基本类型的数据和基本类型的数组数据、String/CharSequence类型的数据和数组数据、实现了Serializable接口或Parcelable接口的对象以及一些Android支持的特殊对象。
      Get:
      Bundle内部其实是实现了Parcelable接口。
    • 使用文件共享
      适合在对数据同步要求不高的进程之间进行通信,并且要妥善处理并发读写的问题。
      Get:
      我们经常使用的Sharepreference属于特殊的文件共享方式,系统对它的读写有一定的缓存策略,会在内存中有一份SharedPreferences文件的缓存,因此在多进程模式下,系统对它的读写就变得不可靠,当面对高并发读写访问的时候,有很大几率会丢失数据,因此,不建议在进程间通信中使用SharedPreferences,更多是在同一个进程或多线程中使用。
    • 使用Messenger(难理解,详见原书)
      Messenger是一种轻量级的IPC方案,它的底层实现就是AIDL,以串行的方式处理客户端发来的消息。
    • 使用AIDL(难理解,详见原书)
    • 客户端通过绑定远程服务,在onServiceConnected方法中将服务器端返回的Binder对象转换成AIDL接口,然后通过这个接口调用服务器端远程方法。
      Get:
      AIDL支持的数据类型:基本数据类型、String、CharSequence、ArrayList、HashMap、Parcelable序列化的对象以及AIDL本身
  • 使用ContentProvider(详见原书)
    【《Android开发艺术探索》读书笔记--part2 IPC进程间通信机制】ContentProvider底层实现了Binder机制,系统已经做了封装,使用时变得简单,需自定义一个类继承 ContentProvider,然后覆写 query、insert、update、delete 等方法,通过URI的匹配来实现增删改查,并在 AndroidManifest 文件中进行注册。
    • 与ContentProvider相关的几个类
      ContentProvider :内容提供者,用于对外提供数据
      ContentResolver :内容解析者,用于获取内容提供者提供的数据
      ContentResolver.notifyChange(uri)发出消息
      ContentObserver :内容监听器,可以监听数据的改变状态
      ContentResolver.registerContentObserver()监听消息
  • 使用Socket(详见原书:基于Socket的简易网络聊天室)
  • part2-4 Binder连接池(详见原书)
    当项目规模很大的时候,创建很多个Service是不对的做法,因为service是系统资源,太多的service会使得应用看起来很重,所以最好是将所有的AIDL放在同一个Service中去管理。整个工作机制是:每个业务模块创建自己的AIDL接口并实现此接口,这个时候不同业务模块之间是不能有耦合的,所有实现细节我们要单独开来,然后向服务端提供自己的唯一标识和其对应的Binder对象;对于服务端来说,只需要一个Service,服务端提供一个queryBinder接口,这个接口能够根据业务模块的特征来返回相应的Binder对象给它们,不同的业务模块拿到所需的Binder对象后就可以进行远程方法调用了。Binder连接池的主要作用就是将每个业务模块的Binder请求统一转发到远程Service去执行,从而避免了重复创建Service的过程。
  • part2-4 选用合适的IPC方式
《Android开发艺术探索》读书笔记--part2 IPC进程间通信机制
文章图片

第二章内容到此结束,主要讲了进程间通信机制,由于比较多涉及到底层原理,所以以目前来说比较难以看懂

    推荐阅读