AIDL在谷歌官方描述中推荐在 不同应用、多并发任务时使用。
在上一篇的基础上,做一些打印和修改。
主要修改:getName方法为耗时方法。即为 getName方法增加 Thread.sleep(20000);
操作演示
1、修改getName为耗时
2、打印客户端代码
点击TextView,开始进行AIDL连接,在 onServiceConnected 中 使用耗时方法 getName,然后打印。
Button按钮用于触发ANR。为什么要用个Button去触发ANR,因为ANR是说APP无响应,是对某一事件无响应,如果你不去主动触发Button 的 onClick方法,那么这个不弹出ANR异常。
那么我们看点击后的效果。
3、点击AIDL连接,查看客户端打印信息
我们看客户端打印信息
01-14 17:02:43.553 26563-26563/com.example.yanlong.aidlclient I/客户端: bindAidl() 函数前一行
01-14 17:02:43.553 26563-26563/com.example.yanlong.aidlclient I/客户端: bindAidl() 函数后一行
01-14 17:02:43.553 26563-26563/com.example.yanlong.aidlclient I/客户端: onServiceConnected 中线程名称main
01-14 17:02:43.553 26563-26563/com.example.yanlong.aidlclient I/客户端: onServiceConnected 中获取到 iUserAidlInterface 对象
01-14 17:03:03.553 26563-26563/com.example.yanlong.aidlclient I/客户端: 您好,我的名字叫服务端
可以看到 最后三行。 主线程、获取对象、调用函数。
在主线程中运行,获取对象和调用函数相差20秒。
这时候我们看服务端打印的信息。
01-14 17:02:43.553 24759-24770/com.example.yanlong.aidlservice I/服务端: Binder_1
服务端当前线程名称为 binder_1 ,是个工作线程。这也正好符合了AIDL的 多并发使用。
既然是 binder_1 可以推测可能会有 binder_2 binder_3 等等一系列。
4、我们点一下 Button 会怎么样?
肯定ANR,不贴图了。
如何修改
1、使用子线程去操作耗时请求
textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.i(TAG, "bindAidl() 函数前一行"); new Thread(new Runnable() { @Override public void run() { bindAidl(); } },"自定义线程").start(); Log.i(TAG, "bindAidl() 函数后一行"); } });
打印结果如下:
01-14 17:48:48.998 14017-14017/com.example.yanlong.aidlclient I/客户端: bindAidl() 函数前一行
01-14 17:48:48.998 14017-14017/com.example.yanlong.aidlclient I/客户端: bindAidl() 函数后一行
01-14 17:48:48.998 14017-14017/com.example.yanlong.aidlclient I/客户端: onServiceConnected 中线程名称main
01-14 17:48:48.998 14017-14017/com.example.yanlong.aidlclient I/客户端: onServiceConnected 中获取到 iUserAidlInterface 对象
01-14 17:49:08.998 14017-14017/com.example.yanlong.aidlclient I/客户端: 您好,我的名字叫服务端
可以明显看出,即使我们使用子线程去进行AIDL连接,
public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG, "onServiceConnected 中线程名称" + Thread.currentThread().getName()); IUserAidlInterface iUserAidlInterface = IUserAidlInterface.Stub.asInterface(service); Log.i(TAG, "onServiceConnected 中获取到 iUserAidlInterface 对象"); try { String name1 = iUserAidlInterface.getName(); Log.i(TAG, name1); } catch (RemoteException e) { e.printStackTrace(); } }onServiceConnected的回调依然是主线程,所以这里建议可以用子线程去开启 AIDL连接,但是一定要在调用远程耗时方法处使用工作线程。
其实从我角度出发来说,只要不涉及到UI更新,我都可能会考虑使用工作线程。当然前提是做好线程同步。