3分钟带你看懂android的Binder机制,手机跨平台开发框架

Binder本质上只是提供了一种通信的方式,和我们具体要实现的内容没有关系,为了实现这个服务,我们需要定义一些接口,让client能够远程调用服务,因为是跨进程,这时候就要设计到代理模式,以接口函数位基准,client和server去实现接口函数,Server是服务真正的实现,client作为一个远程的调用。

  • 从Server进程来看,Binder是存在的实体对象,client通过transact()函数,经过Binder驱动,最终回调到Binder实体的onTransact()函数中。
  • 从 Client进程的角度看,Binder 指的是对 Binder 代理对象,是 Binder 实体对象的一个远程代理,通过Binder驱动进行交互

3.手写进程通信

上面说了那么多,大家伙也看累了,下面通过代码的形式让大家对Binder加深点理解,日常开发中,涉及到进程间通信的话,我们首先想到的可能就是AIDL,但不知道有没有和我感觉一样的朋友。。第一次写AIDL是蒙蔽的,通过.aidl文件,编译器自动生成代码,生成一个java文件,里面又有Stub类,里面还有Proxy类,完全不理解里面的机制,确实不便于我们理解学习,为了加深理解,我们抛弃aidl,手写一个通信代码。

首先我们要定义一个接口服务,也就是上述的服务端要具备的能力来提供给客户端,定义一个接口继承IInterface,代表了服务端的能力

public interface PersonManger extends IInterface {
void addPerson(Person mPerson);
List getPersonList();
}

接下来我们就要定义一个Server中的Binder实体对象了,首先肯定要继承Binder,其次需要实现上面定义好的服务接口

public abstract class BinderObj extends Binder implements PersonManger {
public static final String DESCRIPTOR = “com.example.taolin.hellobinder”;
public static final int TRANSAVTION_getPerson = IBinder.FIRST_CALL_TRANSACTION;
public static final int TRANSAVTION_addPerson = IBinder.FIRST_CALL_TRANSACTION + 1;
public static PersonManger asInterface(IBinder mIBinder){
IInterface iInterface = mIBinder.queryLocalInterface(DESCRIPTOR);
if (null!=iInterface&&iInterface instanceof PersonManger){
return (PersonManger)iInterface;
}
return new Proxy(mIBinder);
}
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
switch (code){
case INTERFACE_TRANSACTION:
reply.writeString(DESCRIPTOR);
return true;

case TRANSAVTION_getPerson:
data.enforceInterface(DESCRIPTOR);
List result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(result);
return true;

case TRANSAVTION_addPerson:
data.enforceInt

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整资料开源分享

erface(DESCRIPTOR);
Person arg0 = null;
if (data.readInt() != 0) {
arg0 = Person.CREATOR.createFromParcel(data);
}
this.addPerson(arg0);
reply.writeNoException();
return true;
}
return super.onTransact(code, data, reply, flags);

}

@Override
public IBinder asBinder() {
return this;
}

}

首先我们看asInterface方法,Binder驱动传来的IBinder对象,通过queryLocalInterface方法,查找本地Binder对象,如果返回的就是PersonManger,说明client和server处于同一个进程,直接返回,如果不是,返回给一个代理对象。

当然作为代理对象,也是需要实现服务接口

public class Proxy implements PersonManger {
private IBinder mIBinder;
public Proxy(IBinder mIBinder) {
this.mIBinder =mIBinder;
}

@Override
public void addPerson(Person mPerson) {
Parcel data = Parcel.obtain();
Parcel replay = Parcel.obtain();

try {
data.writeInterfaceToken(DESCRIPTOR);
if (mPerson != null) {
data.writeInt(1);
mPerson.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mIBinder.transact(BinderObj.TRANSAVTION_addPerson, data, replay, 0);
replay.readException();
} catch (RemoteException e){
e.printStackTrace();
} finally {
replay.recycle();
data.recycle();
}
}

@Override
public List getPersonList() {
Parcel data = Parcel.obtain();
Parcel replay = Parcel.obtain();
List result = null;
try {
data.writeInterfaceToken(DESCRIPTOR);
mIBinder.transact(BinderObj.TRANSAVTION_getPerson, data, replay, 0);
replay.readException();
result = replay.createTypedArrayList(Person.CREATOR);
}catch (RemoteException e){
e.printStackTrace();
} finally{
replay.recycle();
data.recycle();
}
return result;
}

@Override
public IBinder asBinder() {
return null;
}
}

这里的代理对象实质就是client最终拿到的代理服务,通过这个就可以和Server进行通信了,首先通过Parcel将数据序列化,然后调用 remote.transact()将方法code,和data传输过去,对应的会回调在在Server中的onTransact()中

然后是我们的Server进程,onBind方法返回mStub对象,也就是Server中的Binder实体对象

public class ServerSevice extends Service {
private static final String TAG = “ServerSevice”;
private List mPeople = new ArrayList<>();

@Override
public void onCreate() {
mPeople.add(new Person());
super.onCreate();
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return mStub;
}
private BinderObj mStub = new BinderObj() {
@Override
public void addPerson(Person mPerson) {
if (mPerson==null){
mPerson = new Person();
Log.e(TAG,“null obj”);
}
mPeople.add(mPerson);
Log.e(TAG,mPeople.size()+"");
}

@Override
public List getPersonList() {
return mPeople;
}
};
}

最终我们在客户端进程,bindService传入一个ServiceConnection对象,在与服务端建立连接时,通过我们定义好的BinderObj的asInterface方法返回一个代理对象,再调用方法进行交互

public class MainActivity extends AppCompatActivity {
private boolean isConnect = false;
private static final String TAG = “MainActivity”;
private PersonManger personManger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start();
findViewById(R.id.textView).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (personManger==null){
Log.e(TAG,“connect error”);
return;
}
personManger.addPerson(new Person());
Log.e(TAG,personManger.getPersonList().size()+"");
}
});
}

private void start() {
Intent intent = new Intent(this, ServerSevice.class);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其中的binder是重中之重,都说无binderAndroidbinde是Android系统的任督二脉。课程水平循序渐进,由中级再到高级,满足各个层次水平的android开发者。1、灵活使用binder跨进程通信,在app端对它的任何api方法等使用自如2、可以单独分析android系统源码中任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上层的java app端一直到最底层的内核binder驱动,都可以顺利理通5、针对系统开发过程中遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码中使用的socket源码轻松掌握9、android系统源码中最常见的socketpair中双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值