Android Binder入门学习笔记

2019-07-31 09:57| 发布者: |




代理模式相对来说好理解一些,因为在生活中,到处都有代理的影子,比如说我们想去香港买个mac,但是自己不方便去,于是我们找了代购;比如说现在年底了要抢火车票,但是在12306手动抢票根本抢不到啊,所以我们找了第三方抢票软件,它会每隔几十ms就帮我们查询一次,有票的话就帮我们下单。这里就以抢火车票为例来说明代理模式的结构。

proxy


// 声明买票接口
public interface iticket {
 boolean buyticket;
// 官方的12306
public class real12306 implements iticket {
 @override
 public boolean buyticket {
 if  九卅娱乐官方网站网址return true;
 return false;
// 第三方抢票软件
public class thirdparty12306 implements iticket {
 private real12306 real12306;
 public thirdparty12306 {
 this.real12306 = real12306;
 @override
 public boolean buyticket {
 while  {
 if ) {
 return true;
 // 10ms查询一次结果
 try {
 thread.sleep;
 } catch  {
 e.printstacktrace;
public class main {
 public static void main {
 // 初始化我们的购票信息
 real12306 real12306 = new real12306;
 thirdparty12306 thirdparty12306 = new thirdparty12306;
 // 开始不断抢票,释放我们的劳动力
 thirdparty12306.buyticket;
}



package example.com.aidl;
interface imath {
 int add;
}

生成的imath.java文件中,代码有点乱,整理一下之后,结构大致是这样子的:

aidl




class remoteservice : service {
 val math = math
 override fun oncreate {
 super.oncreate
 log.d
 override fun onbind: ibinder {
 return math
 inner class math : imath.stub {
 override fun add: int {
 return a + b
}

// 定义serviceconnection类
inner class myserviceconnection : serviceconnection {
 override fun onservicedisconnected {
 log.d
 override fun onserviceconnected {
 if  return
 // 将ibinder转换成imath
 math = imath.stub.asinterface
 log.d}")
// 在oncreate中绑定remoteservice
val intent = intent
bindservice

当连接上service后,就会回调客户端的onserviceconnected方法,这里传进来的service是一个binderproxy对象。



// imath.java
private static final java.lang.string descriptor = "example.com.aidl.imath";
public static example.com.aidl.imath asinterface {
 if ) {
 return null;
 android.os.iinterface iin = obj.querylocalinterface;
 if  && )) {
 return  iin);
 return new example.com.aidl.imath.stub.proxy ;
// binder.java
public @nullable iinterface querylocalinterface {
 if ) {
 return mowner;
 return null;
}

// imath.java
public stub {
 this.attachinterface;
// binder.java
public void attachinterface {
 mowner = owner;
 mdescriptor = descriptor;
}

return new example.com.aidl.imath.stub.proxy;

@override
public int add throws android.os.remoteexception {
 android.os.parcel _data = android.os.parcel.obtain;
 android.os.parcel _reply = android.os.parcel.obtain ;
 int _result;
 try {
 // 使用parcel来写入数据以便于跨进程传输
 _data.writeinterfacetoken;
 _data.writeint;
 _data.writeint;
 // mremote是在asinterface中获得的binderproxy对象
 mremote.transact;
 // 使用parcel来接收返回值
 _reply.readexception;
 _result = _reply.readint;
 } finally {
 _reply.recycle;
 _data.recycle;
 return _result;
}

@override
public boolean ontransact throws android.os.remoteexception {
 java.lang.string descriptor = descriptor;
 switch {
 case interface_transaction : {
 reply.writestring;
 return true;
 } case transaction_add : {
 data.enforceinterface;
 int _arg0;
 _arg0 = data.readint;
 int _arg1;
 _arg1 = data.readint;
 int _result = this.add;
 reply.writenoexception;
 reply.writeint;
 return true;
 } default: {
 return super.ontransact;
}

在server端收到信息后,会先通过parcel将信息解析出来,然后执行我们调用的add方法,也就是我们在remoteservice中重写imath.stub的add方法。最后将结果写回parcel中再跨进程传回给客户端,从而完成了一次跨进程通信。
如果看到这里,对于binder的流程还有疑惑的话,那就再来一张时序图好了。


binder


从图中我们也可以看出通信过程是同步的。当客户端发起请求的同时,当前的线程会被挂起,直到结果返回。所以要注意的是如果请求太耗时的话,不应该在主线程中去请求,否则容易出现anr。给个systrace直观感受一下。

systrace

相应的cpu信息是处于休眠状态的。

cpu


掌握了binder的上层原理之后,后面再来深入framework层学习就会简单一些,这篇文章也是为了后面的学习打下基础。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对萬仟网的支持。

<
>
关于我们
AB模版网成立于2014年,我们是一家专注用户体验设计开发与互联网品牌建设的设计公司,创立至今为2000多位客户提供了创新与专业的设计方案。设计服务范围包括:交互原型设计、产品视觉设计、网站设计与开发建设、移动及软件产品界面设计、图标设计、品牌及平面设计等。

联系我们

13588889999服务时间:9:00-18:00)

admin@adminbuy.cn

官方微信官方微信

部门热线

前   台:13588889999
业务部:13588889999
客服部:13588889999
技术部:13566667777
人事部:13566667777

咨询电话13588889999 返回顶部
返回顶部