由于嘴贱,立了个flag...
And thanks for this flag ...
To be continued...
Aidl
1)快速上手
-
JavaBean
首先,先写一个JavaBean备用
PS:该文件不要同AIDL文件放置同一个包下,否是运行会提示找不到该类
-
JavaBean.aidl
然后在开始我们新建我们的AIDL文档前,先新建一个与上面JavaBean同名的AIDL文件,既Book.aidl,并在其中声明我们的Book对象
并且该文件需要同上面的JavaBean文件在AIDL下放至于相同的位置,应该是IDE 解析的时候会自动去相同路径下查询,算是一种映射吧,因为待会Sync项目后source下会自动生成java代码,import引用的是aidl路径下的Book.aidl,而这则是由实现了Parcelable的Book.java映射过去的,所以这中间路径需保持一致,不然锁链就断了 (待研究)
-
AIDL
最后我们开始新建真正所要用的AIDL对象:BookManager.aidl,并在其中写入接口函数
在我这小菜鸟现有的理解中,可以暂且将AIDL作为接口来看待,但不同于接口的是
要注意:- 在AIDL文件中使用自定义的JavaBean对象(或非默认数据类型),都必须要在文件中显式地导入进来,正如注释所写的:在此用导入语句来声明任何非默认类型;
- 并且别忘了对象参数的类型定义,既in/out/inout
不然会导致第四步的Sync Project的时候报错......(惨痛经历)
-
Sync Project with Gradle Files
至此,在AS中点击Sync Project同步下项目,编译器将自动根据我们的AIDL文件生成同名的.java文件(若这里忘了同步,则在后续代码的调用将不会有快捷提示了)
生成的.java路径(Project模式下):
-
Service
由于我们的AIDL是跟Service配合使用的,所以我们就接着在Service中创建并调用,具体如下
由于AIDL也是Binder的子类(有点忘了,我后续确认下嘿嘿嘿),所以只要通过binder新建个aidl的对象,然后自然就会重写我们aidl里的方法(这也是为什么我暂且将其作为接口看待的原因)
然后记得在onBind()函数中将上述myBinder返回即可,至此Service部分就写完了
-
Activity
最后是我们的Activity,Activity部分也挺简单的
我们只需要在onServiceConnected()中通过调用AIDL.Stub.asInterface(),并将该方法中的IBinder型参数传入即可,这样我们就获取到了我们的AIDL对象,而后续的事也就是通过该对象来调用之前写在里面的方法罢了
-
结果
2)添加监听
-
新建监听aidl文件:BookListener.aidl,并在其中完善监听接口
-
在BookManager.aidl中也添加注册和解绑监听的方法,记得需要显式导包
-
Service中重写AIDL中两个新添加的方法以实现注册和解绑,并且模拟添加书籍
(模拟添加书籍可参照开发艺术探索P78)
-
Activity中获取BookListener的对象,并重写方法打印,然后记得调用bookManager.registerListener()即可
-
结果:
可以从log里看到,当Activity销毁调用unregisterListener()时,无法找到之前注册的listener
PS:若Service和Activity在同一个进程的情况下,则不会有上述现象
3)使用RemoteCallbackList
由于我们的Service和Activity是在两个进程,而对象不能跨进程传输,而多进程跨进程的话,无法调取到同一对象,因为对象不能跨进程传输,所以Binder会把客户端传递过来的对象重新转换生成一个新的对象,
故若多进程时解绑,需要使用RemoteCallbackList
-
将listenerList类型从List改为RemoteCallbackList
-
重写binder中的注册和解绑函数
需要注意的是RemoteCallbackList的size可以通过beginBroadcast()获取,但需要在调用后,调用finishBroadcast()
-
结果
项目地址:
遗留
- AIDL里的in,out,inout三种类型
- 由于上面只是知其然,还需要看官方文档知其所以然下
Refrence
- 《Android开发艺术探索》