乐于分享
好东西不私藏

学员fw笔记:入门学安卓binder之in、out、inout、oneway

学员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

  1. 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

  1. 通信流程以及生成的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线程流程

在这里插入图片描述

源码

在这里插入图片描述
笔记对应课程如下:
Android Framework开发rom实战合集课表/车载车机手机高级系统开发工程必会技能
1、经典fw的入门到精通实战八件套专题

更多vip免费系统开发经典大厂面试题库获取,课程优惠购买成为vip学员进入vip群,积极讨论各种行业难点痛点疑难问题,答疑服务等。

请联系马哥微信hao:androidframework007