Android ContentProvider原理分析

本文详细分析了Android ContentProvider的原理,包括ContentProvider概述、类图、时序图和源码解析,探讨了ContentProvider在进程间数据交换的角色,以及AMS如何管理ContentProvider的生命周期,强调了跨进程通信的关键点。
摘要由CSDN通过智能技术生成

目录

  • ContentProvider概述
  • 类图
  • 时序图
  • 源码解析
    • installProvider
    • ContentResolver中的CURD
    • acquireProvider
    • 到AMS获取ContentProvider
    • publishContentProvider
    • removeDyingProvider
  • 总结

1. ContentProvider概述

ContentProvider作为Android四大组件之一,重要性肯定是不言而喻的,顾名思义,内容提供者,其最重要的作用就在于提供了一种跨进程获取数据的方式,provider组件不仅可以自己的进程使用,还可以提供给其他的进程使用,大大方便了不同进程之间的数据交换,本文将详细介绍provider运行的原理。
:本文基于Android 8.1

2. 类图

ContentProvider类图
看起来涉及到的类非常多,一下有种不知道从何看起的感觉,所以这里对于其中的重点关注部分加上了颜色:
白色:provider运行过程中涉及到的内部类或私有类,一般APP开发过程中不太会涉及
蓝色:APP开发过程中经常会接触到的类
紫色:在system server进程中provider相关的类

3. 时序图

getContentProvider时序图
其中白色部分:发起获取provider的client进程
红色部分:systemserver进程
蓝色部分:提供provider的server进程
时序图解读:

  1. 1~4流程是在APP自己的进程(进程A)中,一般来讲APP在进程启动之后初始化时,就会installProvider(流程7~10),如果APP请求的provider在自己进程,那么到4就能获取到。
  2. 如果请求的provider另外一个进程(进程B)中,则会触发进程5~6
  3. 如果进程B不存在则先启动进程B并installprovider(7~10),告诉AMS之后,由AMS返回给进程A对方的provider信息(此过程中由进程A发起的请求provider的线程会一直等待)
  4. 如果进程B存在则AMS直接返回给进程A对方的provider信息
  5. 查询到provider信息之后,如果需要跨进程调用,则通过ContentProviderProxy发起binder call到对端进程执行query
    在这其中,AMS充当一个中间管理员的角色,每个进程在启动之后需要把自己应该install的providerinstall之后告诉AMS,这样后面有其他进程请求这个provider的话,AMS可以告诉你所请求的对端的信息。

4. 源码解析

4.1 ActivityThread.installProvider

installProvider,顾名思义就是安装provider,说的通俗一点就是把APP进程中的provider组件封装成对象保存起来,方便使用
在APP的进程启动的时候,handleBindApplication中会触发installProvider:

    private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
        // 此处的provider信息是在AMS启动进程时
        // 从manifest收集到的需要install的provider信息
        final ArrayList<ContentProviderHolder> results = new ArrayList<>();

        for (ProviderInfo cpi : providers) {
            // 执行installProvider,注意此处的stable参数默认为true
            ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
            if (cph != null) {
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }
        try {
            // install完成之后,要告诉AMS
            ActivityManager.getService().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

进一步看一下ActivityThread.installProvider的具体实现

    private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
        ContentProvider localProvider = null;
        IContentProvider provider;
        // holder为null表示还没有install过
        if (holder == null || holder.provider == null) {
            Context c = null;
            ApplicationInfo ai = info.applicationInfo;
            if (context.getPackageName().equals(ai.packageName)) {
                c = context;
            } else if (mInitialApplication != null &&
                    mInitialApplication.getPackageName().equals(ai.packageName)) {
                c = mInitialApplication;
            } else {
                try {
                // 创建context
                    c = context.createPackageContext(ai.packageName,
                            Context.CONTEXT_INCLUDE_CODE);
                } catch (PackageManager.NameNotFoundException e) {
                    // Ignore
                }
            }
            ...
            try {
                final java.lang.ClassLoader cl = c.getClassLoader();
                // 通过反射创建provider对象
                localProvider = (ContentProvider)cl.
                    loadClass(info.name).newInstance();
                // 获取IContentProvider对象,用于跨进程binder call
                provider = localProvider.getIContentProvider();
                if (provider == null) {
                    Slog.e(TAG, "Failed to instantiate class " +
                          info.name + " from sourceDir " +
                          info.applicationInfo.sourceDir);
                    return null;
                }
                // provider的attach,其中最重要的是会执行provider的onCreate
                localProvider.attachInfo(c, info);
            } catch (java.lang.Exception e) {
                if (!mInstrumentation.onException(null, e)) {
                    throw new RuntimeException(
                            "Unable to get provider " + info.name
                            + ": " + e.toString(), e);
                }
                return null;
            }
        } else {
            provider = holder.provider;
        }

        // 到这里,provider的对象创建好了,那么接下来需要做的就是数据结构的封装
        // 把provider相关信息保存起来
        ContentProviderHolder retHolder;
        // mProviderMap的key时providerKey,value是ProviderClientReocrd
        // 这两个类主要是封装了一些provider的基本信息,可以到上面看一下类图
        synchronized (mProviderMap) {
            IBinder jBinder = provider.asBinder();
            if (localProvider != null) {
                ComponentName cname = new ComponentName(info.packageName, info.name);
                // mLocalProvidersByName的key是component信息,value是对应的ProviderClientReocrd
                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
                if (pr != null) {
                    // 不为空代表install过
                    provider = pr.mProvider;
                } else {
                    // 对于新创建的provider,创建其对应的ContentProviderHolder对象
                    holder = new ContentProviderHolder(info);
                    holder.provider = provider;
                    holder.noReleaseNeeded = true;
                    // install Authorities
                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                    // mLocalProviders的key是IContentProvider的binder对象,value是ProviderClientRecord
                    // 将封装好的provider放入map中
                    mLocalProviders.put(jBinder, pr);
                    mLocalProvidersByName.put(cname, pr);
                }
                retHolder = pr.mHolder;
            } else {
                // mProviderRefCountMap的key是binder对象,value是ProviderRefCount
                // ProviderRefCount中记录了这个provider的stable和unstable的数量
                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
                if (prc != null) {
                    if (!noReleaseNeeded) {
                        incProviderRefLocked(prc, stable);
                        try {
                            ActivityManager.getService().removeContentProvider(
                                    holder.connection, stable);
                        } catch (RemoteException e) {
                        }
                    }
                } else {
                    ProviderClientRecord client = installProviderAuthoritiesLocked(
                            provider, localProvider, holder);
                    if (noReleaseNeeded)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值