事先声明,本文所有说法均是临时起意,没有完整代码给予参考
AIDL作用
AIDL(Android Interface Definition Language)是一种用于定义和实现跨进程通信接口的语言。它是 Android 系统中用于进程间通信(IPC)的一种机制,允许一个进程向另一个进程发送请求并获取响应。
从介绍中可与看到,AIDL是被用作跨进程传输数据的一种方式。
有很多人说我开发安卓几年就没用个AIDL,其实也正常,大多APP只有一个进程,用不上这玩意。一个APP里多个进程的操作多数用来做些花里胡哨的操作,比如进程守护、加大内存。但是这里叔劝你一句,没必要,叔怕你把握不住。
回归本质,就让AIDL做它该做的事情,跨进程通信,跨APP通信
AIDL有哪些竞品(我想列哪些就列哪些)
Socket
- 文件共享
startActivity
、startService
、BroadcastReceiver
、ContentProvider
为什么选用AIDL
- 跟
Socket
和文件共享
相比,实现简单。(虽然在很久很久以前,AIDL是手动实现的) - 跟四大组件相比,异步回调简单,这里也许很多人虽然用到过,但是很少意识到四大组件的异步回调
AIDL别人都怎么用
- 定义个aidl文件,声明几个方法
- 再搞个
Service
,在onBind
里返回个binder
对象 - 在某个方法里调用
bindService
,通过ServiceConnection
回调来获取aidl
对象
这么用行不行,行
,大家都这么用绝对是可以的。
但是方便吗?一点也不方便。 我这里说一句,只能异步的操作都不方便,代码还丑,谁赞成谁反对。 谁反对站出来 。
所以题外话, DataStore
NO ,协程
YES。
好了,多余的题外话说完了,diss完别人,到你这又该怎么用。
这种做法我推荐给你
ContentProvider
的结果是同步返回的,可以先这样,再那样:
1.自定义AidlCoreProvider
继承ContentProvider
class AidlCoreProvider : ContentProvider() {
override fun onCreate(): Boolean {
return true
}
override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
return null
}
override fun getType(uri: Uri): String? {
return null
}
override fun insert(uri: Uri, values: ContentValues): Uri? {
return null
}
override fun delete(uri: Uri, selection: String, selectionArgs: Array<String>): Int {
return 0
}
override fun update(uri: Uri, values: ContentValues, selection: String, selectionArgs: Array<String>): Int {
return 0
}
override fun call(method: String?, arg: String?, extras: Bundle?): Bundle {
//这里可以根据条件判断返回具体某个Aidl实现类
val binder = Aidl实现类()
return Bundle().apply { putBinder("key", binder) }
}
}
2.获取`aidl`对象这么搞
```java
private aidl对象 parseAidlService() {
try {
final Uri aidlUri = Uri.parse("content://********");
final ContentResolver resolver = context.getContentResolver();
final Bundle bundle = resolver.call(aidlUri, "", 这里可以搞个条件参数, null);
aidl对象 aidlService = null;
if (bundle != null) {
aidlService = aidl对象.Stub.asInterface(bundle.getBinder("key"));
}
if (aidlService != null) {
return aidlService;
}
} catch (Exception ignored) {
}
return null;
}
科普阶段
aidl
文件方法声明时是可以指定标号的,比如下面这种写法。也许极少数人意识到过,aidl
文件的方法是存在标号的,默认标号以定义方法的顺序为依据,赋值后则赋予的值代表标号。 这在Server
和Client
中aidl
文件有区别时,尤其需要注意,我遇到过有人加aidl
方法直接加在文件中间。aidl
方法的执行主要依靠这个标号,如果标号和方法对不上则会产生问题,会产生什么问题当做叔对你的考验。
interface IAidlInterface {
void basicTypes(int anInt) =1;
}
-
什么时候用
in
、out
、inout
,client
端能改server
端不能改的参数用in
,反过来用out
,两端都想改的用inout
。 实际不需要记,叔教你,先什么都不加,编译不过会报错的,报错了就加inout
,这和直接用public
一样,等到你真正明白之后,再去使用最小限度吧。 -
什么时候用
oneway
,大多数用不上。不关心server
端执行情况的就加这个。但是联系生活,就算真的不关心,也没必要表现出来,我们假装关心一下,也就是不加oneway
。 -
方法数据传输量大怎么办,
aidl
跨进程通信时有数据量限制,太大了受不了。 题外话,为什么要限制大小,限制大小也是限制时间,数据量大传输时间就长,假装aidl
实现是内存共享,空间时间就那么大那么多,不能让你全占了。就跟去医院挂号一样,就一个医生让你用一天,别人看不了病了。 回归正题,数据量就是大怎么办,也能办,分片传输
。 分片实现类参照类android.content.pm.ParceledListSlice
或者android.content.pm.StringParceledListSlice
实现,它可以分片传输List
,是隐藏类,但是可以用,可以使用这个带隐藏类的库。