深入浅出Android-Binder机制(图文+源码深入剖析)

我们来看一眼这个 onTransact

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_increaseCounter:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _result = this.increaseCounter(_arg0);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

是不是非常清晰易懂,就是根据传过来的数据包来做相应的操作,然后把结果写回数据包,Binder 驱动会来帮我们做好这些数据包的分发工作。而这段代码是运行在 Service 本地进程中的,它可以直接调用实现好的 Stub 类中的相关方法(本例子中是 increaseCounter 方法)。

下面我们趁热打铁再来看一眼 Proxy 类中的 increaseCounter 是怎么实现的:

@Override
public int increaseCounter(int increment) throws RemoteException{
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(increment);
mRemote.transact(Stub.TRANSACTION_increaseCounter, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

正好与 Stub 中的处理能够对应起来,其实这两段代码就是整个 IPC 的核心了,Binder 驱动和 Binder 类在底层帮我们做好了其他一切事情。


休息一下。

下面我们来思考另一件事情,如何判断 Service 运行在同一进程还是不同进程?

我们知道,Service 有一个 onBind 方法,这里面就返回了我们实现好的 Stub 类,而客户端 bind service 时拿到的又是一个 IBinder 对象,我们每次只需要调用 StubasInterface 静态方法,把这个 IBinder 对象传进去就能拿到 Stub 类或者 Proxy 类了,看起来十分智能!那么这个 asInterface 又蕴藏什么玄机呢?我们来看一眼实现代码:

public static IBackgroundService asInterface(IBinder obj){
if ((obj==null)) {
return null;
}
IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof IBackgroundService))) {
return ((IBackgroundService) iin);
}
return new IBackgroundService.Stub.Proxy(obj);
}

是不是有点莫名其妙,queryLocalInterface 是什么鬼?
我们再来看看 queryLocalInterface 的实现:

public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}

它判断了一下 descriptor 参数是否与自身 ownerdescriptor 一致,如果一致就直接返回 owner,那么 ownerdescriptor 是在哪被设置的呢,就是在 Stub 的构造函数中被设置的。

于是乎,如果 Service 运行在同一进程,那么客户端拿到的 IBinder 就是 Stub 类,而 StubqueryLocalInterface 又会返回自己;而 Service 运行在单独进程中时,客户端拿到的 IBinder 就是系统提供好的 BinderProxyBinderProxy 中的 queryLocalInterface 默认直接返回 null,根据代码,asInterface 就会构造一个 Proxy 返回给客户端,那么接下来的故事就是上面我们讲过的了。

自己利用 Binder 来进行 IPC

有了上面的基础,其实我们完全不需要 AIDL 了有木有,自己用 Binder 类和 BinderProxy 类就完全可以实现 Service 与客户端的通讯,下面我就速速写一个简单的例子。

尾声

最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

opics/618156601)**

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值