[Android5.1]ContentProvider的Binder通信分析

这篇文章大体介绍一下ContentProvider提供方和使用方之间如何通过binder机制进行通信的。
下面是ContentProvider相关的类图关系:

这里写图片描述

IContentProvider

ContentProvider接口类,继承于IInterface类。该类有两个很重要的子类:ContentProviderNative和ContentProviderProxy,分别为本地服务端和客户端的接口。

ContentProviderProxy

PATH:frameworks/base/core/java/android/content/ContentProviderNative.java
为Content客户端接口。Content使用方获得该接口后,就可以调用接口里的query/insert/delete/update函数进行内容的查询、插入、删除和更新。里面有个IBinder类型的变量mRemote,使用mRemote的transact方法就可以将具体的请求发给binder驱动,binder驱动会进一步将该请求转发给Content提供方。下面以ContentProviderProxy.query为例,看一下具体实现:

public Cursor query(String callingPkg, Uri url, String[] projection, String selection, String[] selectionArgs,
       String sortOrder, ICancellationSignal cancellationSignal) throws RemoteException {    
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    try {
        // 将请求打包到Parceldata.writeInterfaceToken(IContentProvider.descriptor);
        data.writeString(callingPkg);      
        data.writeInt(length);
        ...
        // 将请求包发送给binder驱动。注意这里的请求类型为:IContentProvider.QUERY_TRANSACTION
        mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);   

        // 将返回结果转化为Cursor类型
        if (reply.readInt() != 0) {
            BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
            adaptor.initialize(d);
        } else {
            adaptor.close();
            adaptor = null;
        }
        return adaptor; //返回结果
    } 
}
ContentProviderNative

PATH:frameworks/base/core/java/android/content/ContentProviderNative.java
为Content本地服务端接口,里面有个方法为onTransact,该方法主要是处理来自Content客户端的请求,然后调用其子类Transport来具体实现query/insert/delete/update等具体的操作。下面看一下具体代码:

public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    try {
        switch (code) {
            case QUERY_TRANSACTION:
            {
                ... //解析请求包data

                // 调用子类的query具体实现,即ContentProvider.Transport类。
                Cursor cursor = query(callingPkg, url, projection, selection, selectionArgs,
                        sortOrder, cancellationSignal);

                ... //将处理结果放入返回包reply中

                return true;
            }

            case GET_TYPE_TRANSACTION:  //getType操作
            {
                ...
            }

            case INSERT_TRANSACTION:   //insert操作
            {
                ...
            }

            case DELETE_TRANSACTION:   //delete操作
            {
                ...
            }

            case UPDATE_TRANSACTION:   //update操作
            {
                ...
            }

            ...
        }
    } 
    ...
}
ContentProvider

PATH:frameworks/base/core/java/android/content/ContentProvider.java
该类是一个抽象类,所有的Provider都继承于该类。ContentProvider定义了query/insert/delete/update的接口形式,具体实现由其子类完成。

public abstract class ContentProvider implements ComponentCallbacks2 {
    public abstract Cursor query(Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder);
    public abstract Uri insert(Uri uri, ContentValues values);
    public abstract int delete(Uri uri, String selection, String[] selectionArgs);
    public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs);
    ...
}

ContentProvider中还有一个内部类:Transport,其继承于ContentProviderNative,该类里面实现了query/insert/delete/update方法,由ContentProviderNative.onTransact调用。但这些方法仍然不是最终的实现,还需要进一步调用具体的ContentProvider实现。
下面以Transport.query()为例,看一下具体代码:

class Transport extends ContentProviderNative {
    public Cursor query(String callingPkg, Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder,
            ICancellationSignal cancellationSignal) {
        ...
        try {
            // 由于ContentProvider是抽象类,因此进一步调用ContentProvider的子类的query方法。
            return ContentProvider.this.query(
                    uri, projection, selection, selectionArgs, sortOrder,
                    CancellationSignal.fromTransport(cancellationSignal));
        } finally {
            setCallingPackage(original);
        }
    }
    ...
}
XXXProvider

这里就是系统中某一个ContentProvider的具体实现了,比如MediaProvider、SettingsProvider等。
这些类继承于ContentProvider类,因此必须要实现ContentProvider类中定义的query/insert/delete/update抽象方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值