2、AIDL中线程问题

AIDL在谷歌官方描述中推荐在 不同应用、多并发任务时使用。

在上一篇的基础上,做一些打印和修改。

主要修改:getName方法为耗时方法。即为 getName方法增加 Thread.sleep(20000);

操作演示

1、修改getName为耗时

2、打印客户端代码

点击TextView,开始进行AIDL连接,在 onServiceConnected 中 使用耗时方法 getName,然后打印。

Button按钮用于触发ANR。为什么要用个Button去触发ANR,因为ANR是说APP无响应,是对某一事件无响应,如果你不去主动触发Button 的 onClick方法,那么这个不弹出ANR异常。

那么我们看点击后的效果。

3、点击AIDL连接,查看客户端打印信息

并没有弹出ANR,因为我点击  “连接AIDL” 按钮后,啥也没做,所以不会触发ANR

我们看客户端打印信息

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、使用子线程去操作耗时请求

两种思路,

①:当 OnClick后,使用工作线程运行其内部的bindAidl();函数。

②:当 准备调用 getName(); 函数时,开启工作线程。

 

真相如何?答案只有一个,就是 只使用 ② 或 ①+② 使用。

我们看一下打印结果

 

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更新,我都可能会考虑使用工作线程。当然前提是做好线程同步。

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值