《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(详见原书)

    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进程间通信机制_第1张图片

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

你可能感兴趣的:(Android开发)