Android多进程三

这篇博客详细介绍了Android中使用AIDL进行进程间通信的过程,包括服务端的AIDL接口创建、远程服务实现、客户端的绑定和服务调用。AIDL支持的数据类型和注意事项,如并发处理和数据同步,以及RemoteCallbackList的使用场景和优势都被提及。此外,还讨论了处理耗时操作防止ANR和权限验证的方法。
摘要由CSDN通过智能技术生成

2018-07-23
下面主要是抄的《Android开发艺术探索》2.4.4章节,看过书的就不用看了。
上一篇主要抄了Messenger来进行进程间通信的方法,可以发现Messenger是以串行的方式处理客户端发来的消息,如果大量的消息同时发送到服务端,服务端仍然只能一个个处理,如果有大量的并发请求,那么用Messenger就不太合适了。同时,Messenger的作用主要是为了传递消息,很多时候我们可能需要跨进程调用服务端的方法,这种情形用Messenger就无法做到了,但是我们可以使用AIDL来实现跨进程的方法调用。AIDL也是Messenger的底层实现,因此Messenger本质上也是AIDL,只不过系统为我们做了封装从而方便上层的调用而已。在上一节中,我们介绍了Binder的概念,大家对Binder也有了一定的了解,在Binder的基础上我们可以更加容易地理解AIDL。这里先介绍使用AIDL来进行进程间通信的流程,分为服务端和客户端两个方面。

服务端

服务端首先要创建一个Service用来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口即可。

客户端

客户端所要做事情就稍微简单一些,首先需要绑定服务端的Service,绑定成功后,将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可以调用AIDL中的方法了。

具体实现方式
AIDL接口的创建

收看看AIDL接口的创建,如下所示创建了一个后缀为AIDL的文件,在里面声明了一个接口和两个方法。创建AIDL文件的方式可以看这个Android多进程(一)

// IBookManager.aidl
package com.huangyuanlove.testandroid;

// Declare any non-default types here with import statements
import com.huangyuanlove.testandroid.Book;
interface IBookManager {
   
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
            List<Book> getBookList();
            void addBook(in Book book);
}

在AIDL文件中,并不是所有的数据类型都是可以使用的,只支持如下几种类型:

  • 基本数据类型(int、long、char、boolean、double等);
  • String和CharSequence;
  • List:只支持ArrayList,里面每个元素都必须能够被AIDL支持;
  • Map:只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value;
  • Parcelable:所有实现了Parcelable接口的对象;
  • AIDL:所有的AIDL接口本身也可以在AIDL文件中使用。

以上6种数据类型就是AIDL所支持的所有类型,其中自定义的Parcelable对象和AIDL对象必须要显式import进来,不管它们是否和当前的AIDL文件位于同一个包内。比如IBookManager.aidl这个文件,里面用到了Book这个类,这个类实现了Parcelable接口并且和IBookManager.aidl位于同一个包中,但是遵守AIDL的规范,我们仍然需要显式地import进来:com.huangyuanlove.testandroid.Book。
另外一个需要注意的地方是,如果AIDL文件中用到了自定义的Parcelable对象,那么必须新建一个和它同名的AIDL文件,并在其中声明它为Parcelable类型。在上面的IBookManager.aidl中,我们用到了Book这个类,所以,我们必须要创建Book.aidl,然后在里面添加如下内容:

package com.huangyuanlove.testandroid;
parcelable Book;
远程服务端Service的实现

上面讲述了如何定义AIDL接口,接下来实现这个接口。先创建一个service,代码如下:

package com.huangyuanlove.testandroid;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class BookManagerService extends Service {
   

    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();

    private Binder mBinder = new IBookManager.Stub() {
   
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
   
        }

        @Override
        public List<Book> getBookList() throws RemoteException {
   
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
   
            mBookList.add(book);
        }
    };

    @Override
    public void onCreate() {
   
        super.onCreate();
        mBookList.add(new Book(1,"Android"));
        mBookList.add(new Book(2,"IOS"));
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
   
        return mBinder;
    }
}

上面是一个服务端Service的典型实现,首先在onCreate中初始化添加了两本图书的信息,然后创建了一个Binder对象并在onBind中返回它,这个对象继承IBookManager.Stub并实现了它内部的AIDL方法,注意这里采用了CopyOnWriteArrayList,这个CopyOnWriteArrayList支持并发读/写。在前面
我们提到,AIDL方法是在服务端的Binder线程池中执行的,因此当多个客户端同时连接的时候,会存在多个线程同时访问的情形,所以我们要在AIDL方法中处理线程同步,而我们这里直接使用CopyOnWriteArrayList来进行自动的线程同步。AIDL中所支持的是抽象的List,而List只是一个接口,因此虽然服务端返回的是CopyOnWriteArrayList,但是在Binder中会按照List的规范去访问数据并最终形成一个新的ArrayList传递给客户端。所以,我们在服务端采用CopyOnWriteArrayList是完全可以的。和此类似的还有ConcurrentHashMap,然后我们需要在XML中注册这个Service:

<service android:name=".BookManagerService"
            android:process=":remote"/>
客户端的实现

客户端的实现就比较简单了,首先要绑定远程服务,绑定成功后将服务端返回的Binder对象转换成AIDL接口,然后就可以通过这个接口去调用服务端的远程方法了,代码如下所示:

public class MainActivity extends AppCompatActivity {
   

    private ServiceConnection mConnection = new ServiceConnection() {
   
        @Override
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值