理解 Android Binder 机制(四):补充篇-AIDL以及Proxy-Stub设计模式

本文详细介绍了Android Binder机制中的通用性接口IBinder,阐述了其作为IPC通信基础的重要性。通过Proxy-Stub设计模式,简化了跨进程通信的复杂性,特别是AIDL工具如何自动生成Proxy和Stub类。文章通过实例展示了AIDL的使用,并分析了同进程与跨进程调用的区别,解释了为何在不同场景下会得到Stub或BinderProxy对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

理解Android Binder机制(三):Java篇时最后面说到了AIDL,本篇将会详细介绍。

前言:

IBinder是Android框架的通用性接口,通用性接口意味着,众人可以共享的接口。由于通用性(或共享性),框架开发者可以藉单一的通用性接口来<包容>形形色色的特殊性接口;具有标准化接口的<减法设计>效果,但又不会减损特性用户或App对特殊性接口的需求。兼顾标准性和特殊性的,是框架通用性接口设计的重要指标;这是任何框架开发里,都必须面对的高度挑战性任务之一。

IBinder通用性接口

大家都知道,当两个类都在同一个进程里执行时,两者之间的沟通,只要采取一般的函数调用(Function Call)就行了,既快速又方便。一旦两个类分别在不同的进程里执行时,两者之间的沟通,就不能采取一般的函数调用途径了。只好采取IPC沟通途径。Android框架的IPC沟通仰赖单一的IBinder通用性接口。如下图:
在这里插入图片描述
这种通用性接口,通常会规划一个抽像基类来实现它;而这抽像基类里则定义了抽象函数。如下图:
在这里插入图片描述
于是,这个抽象基类担任两项任务:

实现了IBinder接口,这是提供给众多Client来使用的外部接口。我们以“CI”(Interface for Client)来表示之。

定义了抽象函数,如上图里的onTransact()函数,成为提供给众多子类别来实现的内部接口。我们以来表示之。

如下图所示:
在这里插入图片描述
由子类来实现内部接口。Binder基类的很重要目的是支持跨进程调用Service,也就是让远程的Client可以跨进程调用某个Service。Binder基类定义于Binder.java档案里:

// Binder.java
public class Binder implements IBinder {
   
   
    ...
	private int mObject;
	public Binder() {
   
   
		init();
		...
	}
	
	public final boolean transact(int code, Parcel data, Parcel reply, int flags)
		throws RemoteException {
   
   
		...
		boolean r = onTransact(code, data, reply, flags);
		return r;
	}
	
	private boolean execTransact(int code, int dataObj, int replyObj, int flags) {
   
   
		Parcel data = Parcel.obtain(dataObj);
		Parcel reply = Parcel.obtain(replyObj);
		boolean res;	
		res = onTransact(code, data, reply, flags);
		...
		return res;
	}
	
	protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
		throws RemoteException {
   
   
	}
	
	private native final void init();
}

Binder基类的主要函数是:

方法 说明
transact 用来实作IBinder的transact()函数接口
execTransact 其角色与transact()函数是相同的,只是这是用来让C/C++本地程序来调用的
onTransact 这是一个抽象函数,让应用子类来覆写(Override)的。上述的transact()和execTransact()两者都是调用onTransact()函数来实现反向调用(IoC, Inversion of Control)的
init 这是一个本地(Native)函数,让JNI模块来实现这个函数。Binder()构造函数(Constructor)会调用这个init()本地函数。

在这里插入图片描述
这个IBinder接口是Binder基类提供给Client的接口,简称为“CI”。于是,Client端调用IBinder接口的transact()函数,透过IPC机制而调用到远方(Remote)的onTransact()函数。
在这里插入图片描述
其实,这个典型的通用性接口设计模式,还有很多种变化的形式。例如下图:
在这里插入图片描述
虽然是一个简单的通用性接口设计模式,但是含有丰富的变化机制。例如上图的机制,就让C/C++层的模块成为架构的掌控者。然而,必须理解到:因为设计(和掌控)了IBinder通用性”接口”设计,才能充分保为了C/C++层的模块的”逻辑”控制权。

例如,Android跨进程通信流程,都由底层Binder驱动模块所掌控,如下图所示:
在这里插入图片描述

通用性接口与Proxy-Stub设计模式

然而,在上图里的Activity里可能有多个函数,例如f1()和f2()等。于是,在Activity里,必须从f1()函数转而调用IBinder.transact()函数。如果我们在上述架构里面,加上一个Stub类别(如下图的BinderStub类别),它实现了Binder.onTransact()函数,如下图所示:
在这里插入图片描述
在框架设计里,myProxy和myStub会是成对的,这称为Proxy-Stub模式。如下图所示:
在这里插入图片描述
采用Proxy-Stub设计模式将IBinder接口包装起来,让App与IBinder接口不再产生高度相依性。其将IBinder接口包装起来,转换出更好用的新接口,如下图里的IA接口:
在这里插入图片描述
Stub类将onTransact()函数隐藏起来,提供一个更具有美感、更亲切的新接口给subBinder类使用。隐藏了onTransact()函数之后,subBinder类的开发者就不必费心去了解onTransact()函数了。
于是,Proxy与Stub两个类遥遥相对,并且将IPC细节知识(例如transact()和onTransact()函数之参数等)包夹起来。由于IBinder接口只提供单一函数(即transact()函数)来进行远距通信,呼叫起来比较不方便。所以Android提供aidl.exe工具来协助产出Proxy和Stub类,以化解这个困难。只要你善于使用开发环境的工具(如Android的aidl.exe软件工具)自动产生Proxy和Stub类的程序代码;那就很方便了。

AIDL

应用在使用Binder写aidl接口的时候正是由于android已经使用Proxy-Stub设计模式封装了onTransact()以及Transact()函数,所以才会很方便使用。
下面通过一个简单的例子来说明:

这是一个简单的aidl调用接口,client合入server端需要保持一致。

package com.example.test1;

public interface IBook {
   
   
	void size();
	void name();
	String getStatus();
}

这是server端实现

public class BookService extends Service {
   
   

    private Binder mBinder = new IBook.Stub() {
   
   
    	@Override
        public void size() throws RemoteException {
   
   
            ...
        }
        @Override
        public void name() throws RemoteException {
   
   
            ...
        }
        @Override
        public String getStatus() throws RemoteException {
   
   
            ...
        }
    };
    
    @Override
    public IBinder onBind(Intent intent) {
   
   
        // TODO Auto-generated method stub
        LOG("BookService onBind mBinder:" +mBinder.getClass().getName
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值