IPC机制

开启多线程

1) 为什么要多线程?

  • 特殊的原因自身需要运行在单独的进程中;
  • 为了加大一个应用可使用的内存(待验证
  • 从其他应用获取数据

2)如何开启多线程?

唯一办法给四大组件在manifest里指定android:process属性。

:newProcessnewProcess的区别在于以:开头的是种简写方式,完整的进程名是包名+:newProcess,并且它是私有的,不可被共享;没有:开头的则是全局进程,通过ShreUID的方式可以和它跑在一个进程中。

3)多进程带来的问题?

分析:一个应用(或者一个进程)会被分配一个单独的虚拟机,不同的虚拟机在内存分配上是不同的地址空间,这样在不同的虚拟机中访问同一个对象就会有多个副本。所有通过内存的数据共享都会失败。

多线程带来的问题:

  • 静态成员和单例模式失效
  • Application会被多次创建
  • 所有内存间的通信全部失效
  • 线程间的同步失效
  • SharedPreferences可靠性下降
    • 属于文件存储,但是系统对它的读写有缓存的策略,即在内存中有份SharedPreferences的换成你。

Serializable 和 Parcelable

  1. serialVersionUID:保证反序列化不会因为结构发生变化而无法解析;
  2. 可重写Serializable的序列化和反序列化的逻辑,只要重写writeObject和readObject方法即可。

区别:

  • Serializable是java种的类,使用简单但是开销很大,序列化和反序列化需要大量的I/O操作;
  • Parcelable则效率更高,但使用少复杂
  • 在内存序列化上,建议使用Parcelable;其他的如存储、网络传输可考虑Serializable;

android中进程通信的方式

1) Bundle

Bundle实现了Parcelable接口,因而可以在不同进程间传输。

2) 文件共享

并发的问题,保证数据可靠

3) Messenger

轻量级的IPC方案,底层实现是AIDL。

messenger工作原理

特点:

  • 服务端一次只处理一个请求,所有的请求都是串行的;
  • 不适合高性能并发数据处理

4) AIDL

aidl文件

支持的数据类型:

  • 基本数据类型
  • List,仅ArrayList
  • Map,仅HashMap
  • Parcelable,所有实现了Parcelable接口的对象
  • AIDL,所有的AIDL接口本身可以再AIDL文件中使用

注意的点:

  • Parcelable和AIDL对象在使用时,必须显式的import进来,不管是否存在于一个包中。
  • 在aidl文件中使用自定义的Parcelable对象,必须新建一个和该对象同名的AIDL文件,并声明为parcelable。
  • 除了基本类型,其他类型都必须标上方向:inoutinout
  • aidl的包结构在服务端和客户端应该保持一致,否则无法解析
AIDL本身的说明

【问题】所有传给server的对象,经过Binder时,binder都会把客户端传过来的对象转换成新的对象。所以,不能说在客户端上equals的对象,在server上也是equals的。

【方案】使用RemoteCallbackList。RemoteCallbackList 内部实现了对象和binder的映射关系。binder在同一个进程中是不变的,这样可以保证即使对象变了,也能找到一一的映射。


server端是不稳定的,随时可能会死掉,所以需要知道连接断开,并重连。

  1. 通过设置DeathRecipient监听;
  2. 另外就是onServiceDisconnected

两者的区别在于onServiceDisconnected是在主线程,而DeathRecipient实在客户端的Binder线程池中。


权限的校验:保证服务端的访问是有限制的,不是随意性的访问。 比如:onBind里校验、onTransact里校验。

5) ContentProvider

contentprovider的底层数据存储可以是数据库、可以是文件,甚至可以是内存对象。只要实现了query、update、insert、delete方法即可(存在多线程并发访问的问题)。

遗留的问题:
1. 数据库的操作学习。
2. 数据库的onUpgrade 和 onDowngrade怎么实现?
3. 如何做到sql注入的预防?

6) Socket

深入理解Binder

Binder可以理解为虚拟的物理设备,它甚至有自己的驱动设备/dev/binder。

aidl生成的java文件分析:

1)首先它会继承IInterface;

2)它会声明在aidl文件中定义的所有方法;同时针对每个方法声明一个整型的id来分别标记(为了在通信的时候,能够知道是请求的哪个方法);

3)内部类:Stub 和 Proxy,Proxy是Stub的内部类 Stub就是一个Binder,继承了Binder。

  • asInterface():用于将服务端的binder对象转换成客户端所需要的AIDL接口类型的对象。
    • 这里会根据服务端和客户端是否位于同一进程返回不同的对象。同一进程的就直接返回Stub对象本身;否则是返回系统封装后的Stub.Proxy。
    • 核心方法:Binder#queryLocalInterface()
  • asBinder():返回当前进程的Binder
  • onTransact():这是Stub的方法,运行在服务端的Binder线程池中,远程请求最终会交给这个方法处理。最终通过reply写入返回值返回给客户端。
    • transact()方法触发;

Binder的工作机制 客户端发起远程请求时,当前的线程会被挂起,直到等到服务端的数据返回,所以aidl是个阻塞操作,不能在主线程中执行。

通信方式总结

  • Bundle简单,只要是四大组件间的进程通信,只能传输Bundle支持的数据类型;
  • file/sharedPreference对并发访问支持的不好;
  • AIDL功能强大,在一对多并发访问时可用
  • Message串行通信,只能支持数据传输,且是Bundle支持的数据类型;
  • ContentProvider对数据访问上功能就比较好;
  • Socket网络数据交换;

results matching ""

    No results matching ""