IPC机制———读书笔记
来源:互联网 发布:甬商贷网络借贷 编辑:程序博客网 时间:2024/05/22 11:46
IPC机制———读书笔记
IPC(Inter-Process Communication)是指两个进程之间进行数据交换的过程。
Android中的多进程模式
开启多进程模式
给四大组件在AndroidMenifest中指定android:process属性。
书中代码如下:
<activity android:name=".SecondActivity" android:configChanges="screenLayout" android:label="@string/app_name" android:process=":remote" /> <activity android:name=".ThirdActivity" android:configChanges="screenLayout" android:label="@string/app_name" android:process="com.ryg.chapter_2.remote" />
多进程模式的运行机制
所有运行在不同进程中的四大组件,只要它们之间需要通过内存来共享数据,都会共享失败,这也是多进程带来的主要影响。
多进程会造成如下问题:
1.静态成员和单例模式完全失效
2.线程同步机制完全失效
3.SharedPreferences的可靠性下降
4.Application会多次创建
不同进程的组件会拥有独立的虚拟机、Application以及独立空间。
IPC基础概念介绍
主要包括:Serializable接口、Parcelable接口以及Binder
Serializable接口、Parcelable接口区别
Serializable是java中的序列化接口,使用起来方便但是开销大,序列化和反序列化过程需要大量I/O操作。而Parcelable是Android中的序列化方式,更适合用于Android平台上,它的效率高主要用在内存序列化上。
Binder的工作机制图
通过书中一实例代码了解Binder:
public interface IBookManager extends android.os.IInterface {/** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.ryg.chapter_2.aidl.IBookManager { private static final java.lang.String DESCRIPTOR = "com.ryg.chapter_2.aidl.IBookManager"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.ryg.chapter_2.aidl.IBookManager interface, * generating a proxy if needed. */ public static com.ryg.chapter_2.aidl.IBookManager asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.ryg.chapter_2.aidl.IBookManager))) { return ((com.ryg.chapter_2.aidl.IBookManager)iin); } return new com.ryg.chapter_2.aidl.IBookManager.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder(){ return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_getBookList: { data.enforceInterface(DESCRIPTOR); java.util.List<com.ryg.chapter_2.aidl.Book> _result = this.getBookList(); reply.writeNoException(); reply.writeTypedList(_result); return true; } case TRANSACTION_addBook: { data.enforceInterface(DESCRIPTOR); com.ryg.chapter_2.aidl.Book _arg0; if ((0!=data.readInt())) { _arg0 = com.ryg.chapter_2.aidl.Book.CREATOR.createFromParcel(data); } else { _arg0 = null; } this.addBook(_arg0); reply.writeNoException(); return true; } case TRANSACTION_registerListener: { data.enforceInterface(DESCRIPTOR); com.ryg.chapter_2.aidl.IOnNewBookArrivedListener _arg0; _arg0 = com.ryg.chapter_2.aidl.IOnNewBookArrivedListener.Stub.asInterface(data.readStrongBinder()); this.registerListener(_arg0); reply.writeNoException(); return true; } case TRANSACTION_unregisterListener: { data.enforceInterface(DESCRIPTOR); com.ryg.chapter_2.aidl.IOnNewBookArrivedListener _arg0; _arg0 = com.ryg.chapter_2.aidl.IOnNewBookArrivedListener.Stub.asInterface(data.readStrongBinder()); this.unregisterListener(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.ryg.chapter_2.aidl.IBookManager { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote){ mRemote = remote; } @Override public android.os.IBinder asBinder(){ return mRemote; } public java.lang.String getInterfaceDescriptor(){ return DESCRIPTOR; } @Override public java.util.List<com.ryg.chapter_2.aidl.Book> getBookList() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.util.List<com.ryg.chapter_2.aidl.Book> _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0); _reply.readException(); _result = _reply.createTypedArrayList(com.ryg.chapter_2.aidl.Book.CREATOR); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public void addBook(com.ryg.chapter_2.aidl.Book book) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); if ((book!=null)) { _data.writeInt(1); book.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public void registerListener(com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeStrongBinder((((listener!=null))?(listener.asBinder()):(null))); mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public void unregisterListener(com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeStrongBinder((((listener!=null))?(listener.asBinder()):(null))); mRemote.transact(Stub.TRANSACTION_unregisterListener, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); static final int TRANSACTION_registerListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); static final int TRANSACTION_unregisterListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3); } public java.util.List<com.ryg.chapter_2.aidl.Book> getBookList() throws android.os.RemoteException; public void addBook(com.ryg.chapter_2.aidl.Book book) throws android.os.RemoteException; public void registerListener(com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException; public void unregisterListener(com.ryg.chapter_2.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException;}
代码具体解析这里就不贴了,可以查看书中讲解。
需要注意:
1.当客户端发起远程请求时,由于当前线程会被挂起直至服务端进程返回数据,所以一个远程方法是很耗时的,不能在UI线程中发起此请求。
2.由于服务端的Binder方法运行在Binder线程池中,所以Binder方法不管是否耗时都应该采用同步的方式去实现。
Android中的IPC方式
1.Bundle
2.文件共享(不建议使用系统的SharedPreferences)
3.Messenger(轻量级IPC,底层依然是AIDL)工作原理(Page70 & 代码)
4.AIDL4.1. AIDL支持的数据类型:基本数据类型;String和CharSequence;List只支持ArrayList,里面每个元素都必须被AIDL支持;Map只支持HashMap,里面每个元素都必须被AIDL支持(包括key和value);Parcelable;AIDL接口本身;4.2. 服务端可以使用CopyOnWriteArrayList和ConcurrentHashMap来进行自动线程同步,客户端拿到的依然是ArrayList和HashMap;4.3. 服务端和客户端之间做监听器,服务端需要使用RemoteCallbackList,否则客户端的监听器无法收到通知(因为服务端实质还是一份新的序列化后的监听器实例,并不是客户端那份);dd. 客户端调用远程服务方法时,因为远程方法运行在服务端的binder线程池中,同时客户端线程会被挂起,所以如果该方法过于耗时,而客户端又是UI线程,会导致ANR,所以当确认该远程方法是耗时操作时,应避免客户端在UI线程中调用该方法。同理,当服务器调用客户端的listener方法时,该方法也运行在客户端的binder线程池中,所以如果该方法也是耗时操作,请确认运行在服务端的非UI线程中。另外,因为客户端的回调listener运行在binder线程池中,所以更新UI需要用到handler。4.4. 客户端通过IBinder.DeathRecipient来监听Binder死亡,也可以在onServiceDisconnected中监听并重连服务端。区别在于前者是在binder线程池中,访问UI需要用Handler,后者则是UI线程。4.5. 可通过自定义权限在onBind或者onTransact中进行权限验证。
5.ContentProvider
6.Socket 一般用于网络通信,AIDL用这种方式会过于繁琐,不建议。
7.Binder连接池,通过BinderPool的方式将Binder的控制与Service本身解耦,同时只需要维护一份Service即可。这里用到了CountDownLatch,大概解释下用意:线程在await后等待,直到CountDownLatch的计数为0,BinderPool里使用它的目的是为了保证Activity获取BinderPool的时候Service已确定bind完成。
- IPC机制———读书笔记
- 《Android开发艺术探索》读书笔记——IPC机制
- Android读书笔记-------IPC机制
- 读书笔记--IPC机制(二)
- 读书笔记--IPC机制(三)
- IPC机制读书笔记
- 读书笔记(2) IPC机制
- Android IPC机制——Binder详解
- Android的IPC机制——Binder
- Android中的IPC机制——Binder
- 读书笔记--IPC机制(一)
- 读书笔记--IPC机制(四)
- [读书笔记]Android IPC机制(一)
- Android——IPC机制(一)IPC概念以及Binder机制
- Android开发艺术探索读书笔记-IPC机制
- IPC机制——AIDL——Binder“连接池”
- 001——Binder 机制详解—Binder IPC 程序结构
- Android的IPC机制——Binder (1)
- [学习笔记]Java正则表达式
- CentOS6.5安装(硬盘空间大于16T)
- HDU 1028 Ignatius and the Princess III(母函数或dp)
- Google Code Jam 2016 Round 1A
- 2016SDAU编程练习二1005
- IPC机制———读书笔记
- test
- mysql中的当前时间函数
- 【学习C++】C++ Primer Plus (第六版)第七章编程练习6-10
- B 树、B- 树、B+ 树、B* 树都是什么
- POJ NO.2367 Genealogical tree(简单拓扑排序,典例)
- QT中QProcess调用命令行的痛苦经历
- Cache
- 10种linux下磁盘快照方式恢复系统