3.1 AIDL是怎么工作的?
我们编写了aidl文件之后,啥也没干就自动拥有了跨进程通信的能力.这一切得归功于Android Studio根据aidl文件生成的IPersonManager.java
文件(生成的这个文件通过双击Shift输入IPersonManager.java
即可找到),它里面已经帮我们封装好了跨进程通信这块的逻辑(最终是通过Binder来完成的),所以这个IPersonManager.java
文件最终会打包进apk里面,我们才得以方便地进行跨进程通信.
3.2 详细解读
先来简单看下IPersonManager.java
的大致结构,为了更方便阅读,我将IPersonManager.aidl
文件中多余的方法全部删除,只剩下List<Person> getPersonList();
和void addPersonIn(in Person person);
:
/*
- This file is auto-generated. DO NOT MODIFY.
*/
package com.xfhy.allinone.ipc.aidl;
public interface IPersonManager extends android.os.IInterface {
/**
- Default implementation for IPersonManager.
*/
public static class Default implements com.xfhy.allinone.ipc.aidl.IPersonManager {
@Override
public java.util.List<com.xfhy.allinone.ipc.aidl.Person> getPersonList() throws android.os.RemoteException {
return null;
}
@Override
public void addPersonIn(com.xfhy.allinone.ipc.aidl.Person person) throws android.os.RemoteException {
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/**
- Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.xfhy.allinone.ipc.aidl.IPersonManager {
private static final java.lang.String DESCRIPTOR = “com.xfhy.allinone.ipc.aidl.IPersonManager”;
/**
- Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
-
Cast an IBinder object into an com.xfhy.allinone.ipc.aidl.IPersonManager interface,
-
generating a proxy if needed.
*/
public static com.xfhy.allinone.ipc.aidl.IPersonManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.xfhy.allinone.ipc.aidl.IPersonManager))) {
return ((com.xfhy.allinone.ipc.aidl.IPersonManager) iin);
}
return new com.xfhy.allinone.ipc.aidl.IPersonManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_getPersonList: {
data.enforceInterface(descriptor);
java.util.List<com.xfhy.allinone.ipc.aidl.Person> _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addPersonIn: {
data.enforceInterface(descriptor);
com.xfhy.allinone.ipc.aidl.Person _arg0;
if ((0 != data.readInt())) {
_arg0 = com.xfhy.allinone.ipc.aidl.Person.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addPersonIn(_arg0);
reply.writeNoException();
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.xfhy.allinone.ipc.aidl.IPersonManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public java.util.List<com.xfhy.allinone.ipc.aidl.Person> getPersonList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.xfhy.allinone.ipc.aidl.Person> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getPersonList();
}
_reply.readException();
_result = _reply.createTypedArrayList(com.xfhy.allinone.ipc.aidl.Person.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addPersonIn(com.xfhy.allinone.ipc.aidl.Person person) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((person != null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
boolean _status = mRemote.transact(Stub.TRANSACTION_addPersonIn, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().addPersonIn(person);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
public static com.xfhy.allinone.ipc.aidl.IPersonManager sDefaultImpl;
}
static final int TRANSACTION_getPersonList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addPersonIn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(com.xfhy.allinone.ipc.aidl.IPersonManager impl) {
// Only one user of this interface can use this function
// at a time. This is a heuristic to detect if two different
// users in the same process use this function.
if (Stub.Proxy.sDefaultImpl != null) {
throw new IllegalStateException(“setDefaultImpl() called twice”);
}
if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.xfhy.allinone.ipc.aidl.IPersonManager getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public java.util.List<com.xfhy.allinone.ipc.aidl.Person> getPersonList() throws android.os.RemoteException;
public void addPersonIn(com.xfhy.allinone.ipc.aidl.Person person) throws android.os.RemoteException;
}
这块代码看起来很长.咱依次来看,首先IPersonManager是一个接口,然后它继承自IInterface接口.IInterface接口是Binder接口的基类,要通过Binder传输的接口都必须继承自IInterface.它里面的方法就是我们在aidl文件中声明的2个方法.然后用2个整型的id用于标识在transact过程中客户端所请求的是哪个方法.IPersonManager.Stub继承自Binder并实现了IPersonManager接口.当客户端与服务端都位于同一个进程时,方法调用不会走跨进程的transact过程,而当两者位于不同进程时,方法调用需要走transact过程,这个逻辑是由Stub的内部代理Proxy完成的.
Default类就只是IPersonManager的默认实现,可以不用在意.
下面来单独分析一下Stub类
IPersonManager.Stub
public static abstract class Stub extends android.os.Binder implements com.xfhy.allinone.ipc.aidl.IPersonManager {
private static final java.lang.String DESCRIPTOR = “com.xfhy.allinone.ipc.aidl.IPersonManager”;
/**
- Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
-
Cast an IBinder object into an com.xfhy.allinone.ipc.aidl.IPersonManager interface,
-
generating a proxy if needed.
*/
public static com.xfhy.allinone.ipc.aidl.IPersonManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.xfhy.allinone.ipc.aidl.IPersonManager))) {
return ((com.xfhy.allinone.ipc.aidl.IPersonManager) iin);
}
return new com.xfhy.allinone.ipc.aidl.IPersonManager.Stub.Proxy(obj);
}
}
-
DESCRIPTOR是Binder的唯一标识,一般用当前Binder的类名表示.
-
attachInterface()是将Binder对象转成客户端需要的AIDL接口类型对象.如果需要跨进程,则还需要封装一个Stub.Proxy对象再返回;如果不需要跨进程,那么直接将Service端的Stub直接返回就行.
接着看Stub剩余的方法:
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_getPersonList: {
data.enforceInterface(descriptor);
java.util.List<com.xfhy.allinone.ipc.aidl.Person> _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addPersonIn: {
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
roid核心高级技术PDF文档,BAT大厂面试真题解析】**
[外链图片转存中…(img-fcWOoE6R-1714643545207)]
【算法合集】
[外链图片转存中…(img-QcEUfypC-1714643545211)]
【延伸Android必备知识点】
[外链图片转存中…(img-NAf80pTo-1714643545213)]
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!