Android 多进程通讯之几个基本问题

Android多进程系列

开启多进程的方法

Android 中使用多进程只有一种方法,那就是给四大组件(Activity、Service、Receiver、ContentProvider)在AndroidMenifest中指定android:process属性android

<service
    android:name="com.xxq2dream.service.BookManagerService"
    android:process=":remote" />
复制代码
  • 经过如上的设置,BookManagerService就运行在独立的进程下,进程名为:包名:remote,好比:com.xxq2dream.android_ipc:remote
  • 上面的设置方法表示remote进程是当前应用的私有进程,其余应用的组件不能够和它跑在同一个进程中
  • android:process属性的设置还有另外一种方式com.xxq2dream.android_ipc.remote,这种方式的进程是全局进程,其余应用经过ShareUID方式能够和它跑在同一个进程中。
  • 通常咱们在应用中用的比较多的是第一种,也便是应用的私有进程

开启多进程模式后的问题

Android为每一个进程都分配一个独立的虚拟机,不一样的虚拟机在内存分配上有不一样的地址空间,这就致使了不一样的虚拟机中访问同一个类的对象会产生多个副本。一个应用间的多进程能够理解为就至关于2个不一样的应用采用了SharedUID的模式。缓存

  • 全部运行在不一样的进程中的四大组件,只要它们之间须要经过内存来共享数据,都会共享失败
  • 静态成员和单例模式彻底失效(不一样进程的内存区域都不同了)
  • 线程同步机制彻底失效(不一样的进程锁的都不是同一个对象)
  • Application会屡次建立
  • SharedPreferce的可靠性降低(SharedPreferce底层是读写xml文件实现的,系统对它的读写有必定的缓存策略,在内存中会有一份SharedPreferce文件的缓存,因此多个进程并发写操做可能致使数据丢失)

多进程通讯的实现方式

使用Bundle
  • 四大组件中的三大组件(Activity、Service、Receiver)都支持在Intent中传递Bundle数据
  • Bundle中的数据除了基本类型,其余的都须要可序列化
  • 适用于从一个进程启动另外一个进程,好比在一个进程中启动另外一个进程中的Activity、Service、Receiver,与此同时传递数据的状况
使用文件共享
  • 2个进程经过读写同一个文件来交换数据
  • 固然要把数据写入文件,必然要求数据能够序列化和反序列化
  • 文件共享对文件格式没有要求,只要读写双方约定好数据格式
  • 文件共享的方式存在并发读写的问题,适合对数据同步要求不高的进程间通讯,而且要妥善处理并发读写的问题
使用Messager
  • 使用Messager来传递Message,Message中能使用的字段只有what、arg一、arg二、Bundle和replyTo,自定义的Parcelable对象没法经过object字段来传输
  • Message中的Bundle支持多种数据类型,replyTo字段用于传输Messager对象,以便进程间相互通讯
  • Messager以串行的方式处理客户端发来的消息,不适合有大量并发的请求
  • Messager方法只能传递消息,不能跨进程调用方法
使用AIDL
  • AIDL接口能够经过编写AIDL文件而后由系统生成对应的Binder类,经过Binder咱们就能够进行跨进程通讯了
  • AIDL文件中只支持以下几种类型:
    • 基本类型,如int、long等
    • String和CharSequence
    • List:只支持ArrayList,里面的每一个元素都必须被AIDL支持
    • Map:只支持HashMap,里面的key、value都必须被AIDL支持
    • AIDL:全部的AIDL接口自己也能够在AIDL文件中使用
  • AIDL文件中用到的自定义Parcelable对象和AIDL对象必需要显示的import进来
  • 出了基本数据类型,其余类型的参数必须标明是入参仍是出参,in表示输入型参数,out表示输出型参数,inout表示输入输出型参数

序列化之Serializable接口和Parcelable接口

  • Serializable接口和Parcelable接口都能实现序列化,可是有区别
Serializable接口
  • Serializable接口实现序列化比较简单,只须要在须要实现序列化的类实现Serializable接口就行
  • serialVersionUID能够指定也能够不指定,不指定的话系统会默认给咱们生成
  • serialVersionUID的做用是用于标识当前类的版本,便于在反序列化过程当中判断类是否有更改,若是serialVersionUID不一致,反序列化就会失败
  • 人为指定serialVersionUID后,若是不是破坏性的改动了类,好比版本升级后增长了一个字段,那反序列化之后仍然能成功;而若是没有指定,反序列化就会失败
  • serialVersionUID是否指定须要根据具体的须要来肯定
  • 静态成员变量和transient关键字标记的变量不参与序列化过程
Parcelable接口
  • Parcelable接口实现序列化稍微复杂,须要实现writeToParcel方法、describeContents方法以及生成器Creator
  • 内容描述功能的describeContents方法通常都返回0,当当前对象中存在文件描述符时才返回1
  • Parcelable接口中的Parcel内部包装了可序列化的数据,能够在Binder中自由传输
Parcelable接口和Serializable接口
  • Serializable接口是Java中的序列化接口,使用简单可是开销大,序列化和反序列化过程须要大量的I/O操做,通常用于将对象序列化到存储设备中或是将对象序列化后经过网络进行传输
  • Parcelable接口是Android中的序列化方式,使用稍微麻烦,可是效率很高,是Android中推荐的序列化方式,主要用在内存序列化上

欢迎关注个人微信公众号,和我一块儿学习一块儿成长!
复制代码

AntDream
相关文章
相关标签/搜索