学员fw笔记:入门学安卓binder之in、out、inout、oneway
感谢学员朋友秋双jack分享他学习binder课程的相关详细笔记,这里公开给大家方便大家复习,这里为他的分享点赞哈!
@
- 1.AIDL
- 2.in、out、inout、oneway关键字
- 2.1 oneway关键字
- 2.1 参数关键字in、out、inout
- 3.支持的数据类型
- 4.双向通信Demo
- 5.Messenger
- 6.java开启binder线程池
- 6.1 启动binder相关类ProcessState
- 6.2 启动binder线程池
1.AIDL
-
AIDL是什么
AIDL是Android接口定义语言,来帮助binder跨进程通信的接口定义而设计的一个语言。会通过一个aidl.exe把整个aidl文件都转换成对应的java文件。

手动调用aidl生成java文件
aidl.exe -IF:\binder_drivers_code\ServiceDemo\app\src\main\aidl\com\example\servicedemo F:\binder_drivers_code\ServiceDemo\app\src\main\aidl\com\example\servicedemo\IStudentInterface.aidl
-
通信流程以及生成的Stub类、Proxy类成员

-
手动编写时注意客户端和服务端的 DESCRIPTOR要保持一致,否则data.enforceInterface会报错 -
客户端获取服务端Stub的两种方式:①binderService回调中获取;②getService直接获取。 -
客户端通过data向服务端传参,服务端通过reply返回数据给客户端
2.in、out、inout、oneway关键字
2.1 oneway关键字
-
异步 -
修饰void方法; -
修饰interface;
2.1 参数关键字in、out、inout
-
in 数据只能由客户端向服务端,服务端修改对象参数不影响客户端 -
out 只能由服务端修改,服务端收到的对象的参数null,客户端修改之后服务端看不见 -
inout 双向流通
3.支持的数据类型
1. Java 的原生类型2. String 和CharSequence3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型; 以上三种类型都不需要导入(import)4. AIDL 自动生成的接口 需要导入(import)5. 实现android.os.Parcelable 接口的类. 需要导入(import)。
4.双向通信Demo
客户端
Messenger messengerClientSend = new Messenger(messengerHandler); Messenger messengerServer = null; Intent intent = new Intent(MainActivity.this,MyService.class);// startService(intent); bindService(intent, new ServiceConnection() {@OverridepublicvoidonServiceConnected(ComponentName name, IBinder service){ IStudentInterface remoteInterface = IStudentInterface.Stub.asInterface(service);try { remoteInterface.setCallback(new CallbackeService()); } catch (RemoteException e) { e.printStackTrace(); } }@OverridepublicvoidonServiceDisconnected(ComponentName name){// 服务端挂掉 } }, BIND_AUTO_CREATE); }
服务端
public IBinder onBind(Intent intent){// TODO: Return the communication channel to the service.return mBinder; } IChangeCallback mCallBack = null; IStudentInterface.Stub mBinder = new IStudentInterface.Stub() {@OverridepublicvoidsetCallback(IChangeCallback callback)throws RemoteException { mCallBack = callback; mCallBack.asBinder().linkToDeath(new DeathRecipient() {@OverridepublicvoidbinderDied(){ } },0); } }
onDestroy和linkToDeath回调

1.客户端unbindService或者activity.finish,服务端回调onDestroy; 2.杀死activity进程,服务端先linkToDeath,再onDestroy,如下图。

客户端调用到服务端setCallback时,如果服务端执行过程中直接抛异常,是抛给客户端进程的,服务端不会挂。除非是在新线程中抛的。
5.Messenger
基本使用流程

Message源码

6.java开启binder线程池
6.1 启动binder相关类ProcessState
ProcessState::self()->startThreadPool()和IPCThreadState::self()->joinThreadPool()的区别
6.1.1区别
ProcessState::self()->startThreadPool()告诉 Binder 驱动,当前进程需要启动一个线程池。它会创建额外的线程(默认可能是一个或多个),每个线程都会执行 IPCThreadState::self()->joinThreadPool()。这是一个非阻塞调用,它会立即返回,不会卡住当前线程。IPCThreadState::self()->joinThreadPool(true)让当前线程进入 Binder 处理循环,不断等待并处理 Binder 事务。这是一个阻塞调用,调用后的代码不会执行。
6.1.2使用场景
intmain(){// ... 注册服务 ... IPCThreadState::self()->joinThreadPool(true); // 主线程自己进入循环// 永远不会执行到这里}
intmain(){// ... 注册服务 ... ProcessState::self()->startThreadPool(); // 创建额外的Binder线程 IPCThreadState::self()->joinThreadPool(true); // 主线程也加入循环// 永远不会执行到这里}
intmain(){// ... 注册服务 ... ProcessState::self()->startThreadPool(); // 额外线程处理请求// 主线程继续做其他工作,比如循环处理其他事情while (true) { do_some_work(); sleep(1); }return0;}
例如onZygoteInit()就是第三种,启动binder线程池,后续主线程继续做自己的事

6.2 启动binder线程池
sp<ProcessState> proc = ProcessState::self();proc->startThreadPool();
binder线程流程

源码


更多vip免费系统开发经典大厂面试题库获取,课程优惠购买成为vip学员进入vip群,积极讨论各种行业难点痛点疑难问题,答疑服务等。
请联系马哥微信hao:androidframework007
夜雨聆风