Android开发艺术探索学习笔记2——IPC机制
2017-09-24 12:05
525 查看
Android开发艺术探索学习笔记2——IPC机制
IPC简介:
Windows上的IPC:剪贴板:所有的进程都可以设置和修改剪贴板,也都可以从剪贴板获取内容
管道:实质是一种共享的内存,由一个进程创建,其他进程连接,并可进行双向的通信。
邮槽:一个进程创建并拥有一个邮槽,其他进程都可以打开这个邮槽并向其发送消息。
Linux上的IPC:
管道:用来连接不同进程之间的数据流。
共享内存:允许两个或多个进程共享一定的存储区,因为不需要拷贝数据,所以这是最快的一种IPC。
信号量:信号是一种异步通信机制, 信号异步通知接收信号的进程发生了某个事件。
Android上IPC:
除了继承自Linux的IPC之外还有Android特有的Binder。
这里还有Socket和ContentProvider也可以算作是进程间通信。
Android中多进程
多进程的开启:
通过android:process = “:进程名” 属性开启。在安卓中每个进程都分配一个独立的虚拟机,虚拟机有不同的地址空间和对象副本。
跨进程带来的问题
因此不同的进程就拥有独立的:1、虚拟机2、Application 3、内存空间。则多进程造成的问题如下:
1. 静态成员和单例模式完全失效(内存不共享)
2. 线程同步机制完全失效(内存不共享)
3. SharedPreference的可靠性下降(谷歌已经废弃,不推荐)
4. Application多次创建(因为不同进程在不同的虚拟机,启动新的虚拟机又会将当前应用跑一遍)
跨进程的解决方式
Android中的跨进程通信:1、Intent来传递2、共享文件 3、SharePreference4、基于Binder的Messager 5、AIDL 5、SocketIPC的基础概念
Serializable接口:
这是java提供的一个序列化接口。Serializable序列化对象会有一个serialVersionUID。在反序列化时,需要serialVersionUID和当前类相同才能够被正常反序列化。当类结构发生改变时serialVersionUID会变更。这会导致用原来类结构序列化的对象反序列化会不成功。所以一般选择手动赋值。
Parcelable接口:
这是Android提供的一个序列化接口。相对于Serializable,Parcelable在Android上的序列化效率更高。
Binder:
Binder采用的是C/S结构,通过ServiceManager连接各种Manager(ActivityManager、WindowManager等)。在AIDL过程中系统会生成对应的.aidl对象,里面的Binder也是自动生成的,同时对应的方法也会在onTransact方法中生成跨进程的方法。
当客户端和服务端在同一个进程时,方法不会走跨进程的transact过程,当跨进程时,方法需要走tracsact过程,并通过Stub(即binder)的内部代理类Proxy来完成。
在这里AIDL仅仅是我们生成Binder的工具。
Android中的IPC机制:
使用Bundle
在bundle中放入序列化对象,之后通过Intent进行传输。使用文件共享
通过文件存储和共享是比较普遍和简单的方法同时,这里的SharedPreference也是个典型例子。
使用Messenger
它是一个轻量级的IPC方案,底层实现是AIDL。不过整个通信过程是以串行的方式进行,不适合大批量的并发请求。在Messenger通信过程中,处理message是在Handler中进行的。A要发送信息给B需要持有B的Messager对象才行。
客户端向服务器发送信息
服务端:客户端:
messager要实现通信,需要对方持有自己的messager对象。在Service中Messager对象是通过onBinder返回给客户端的。
服务器向客户端发送信息:
服务器改动:客户端的改动:
因为客户端要处理Message所以需要创建Handler和自己的Messager,通过Message的replyTo将自己的Messager对象发送给服务端。
使用AIDL
普通的使用
服务端:在aidl文件夹中建立aidl的接口:
注意:aidl服务所在包名最好和客户端的包名结构一致。
Eg:
这是我的一个应用的aidl
客户端的实现:
通过binderService的方式去绑定服务并获取binder,从而实现和服务器的通信。这里,除了用到了aidl文件基本上整体和进程内与service通信没什么区别。
客户端对服务器的监听:
服务器端修改:在aidl文件中建立一个.aidl的接口文件:
然后给原来的IBookManager添加注册监听和取消监听的方法
相应的在主工程下实现,将监听放到一个管理监听的ArrayList中
在收到新书之后去通知对应的监听列表
客户端修改:
在获取服务端的binder之后向其注册监听
在onDestroy时解注册监听:
但这里会报错:
监听异常的注意事项:
对象跨进程的本质;Binder会把客户传递过来的序列化对象转化并生成一个新的对象。为了防止这个异常,Android提供了RemoteCallbackList专门用来保存在服务端的监听。但这个RemoteCallbackList使用方法很特殊:
AIDL的其他注意事项:
1、 无论是在服务端还是客户端最好都运行在非UI线程中2、 对于服务端意外死亡的情况,我们最好为服务设置死亡监听DeathRecipient,从而重连远程服务。
3、 AIDL权限验证:
客户端验证:
a) 在要使用该该服务的Mainifest中添加permission权限
b) 在obBind方法中添加验证方法
服务端验证:
在服务端的onTransact中进行验证,用户的Uid和Pid。注意:要使用我们的自定义权限的包名必须以com.ryg开始。
使用ContentProvider
其底层也是采用Binder。看似是SQLite数据库,实际上对于数据存储的方式没有要求。主要针对的数据格式为:1、表格的形式2、文件数据(图片、视频等)
监听:在update、insert和delete方法引起数据源改变的时候,可以通过ContentResolver的notifyChange来通知外界。
并发:query、update、insert、delete存在多线程并发,需要做好线程同步。
使用socket
不能在主线程中访问网络。Binder连接池
对于多个地方使用到aidl的情况(每个aidl通信都要通过service),为了节省资源,我们将所有aidl放到同一个Service中去处理。用法:
在aidl文件中申明一个IBinderPool接口
在service中实现为:
整体实现:
调用方法:
AIDL的选择:
相关文章推荐
- 《Android 开发艺术探索》——View 事件体系--View基础知识 (学习笔记)
- Android开发艺术探索学习笔记
- Android开发艺术探索学习笔记1——Avtivity生命周期和启动模式
- Android开发艺术探索——学习笔记_View事件体系
- Android开发艺术探索学习笔记(六)
- Android开发艺术探索学习笔记 第一章
- Android开发艺术探索 学习笔记
- Android 开发艺术探索 学习笔记 Activity
- android开发艺术探索 学习笔记(一) Activity生命周期全面分析
- android开发艺术探索 学习笔记(二) Activity的启动模式
- Android开发艺术探索学习笔记6——线程和线程池
- android开发艺术探索 学习笔记(三) IntentFilter的匹配规则
- 《Android 开发艺术探索》笔记——(3)View 的事件体系
- Android——View的事件分发机制(学习Android开发艺术探索)
- Android艺术开发探索学习 之 测量view的宽高 以及 动态设置View的位置
- Android——自定义View(学习Android开发与艺术探索)
- 利用Window和WindowManager实现悬浮窗效果——Android开发艺术探索笔记
- android开发艺术探索学习 之 Activity的生命周期
- Android开发艺术探索(研读笔记)——03-Android中的IPC机制(一)
- View的滑动冲突解决-android开发艺术探索笔记