Android内容提供者(ContentProvider)浅析(一)

ContentProvider是Android系统四大基本组件中涉及到数据共享的重要角色。本文将对它的一些知识做一些简介来引导大家更好的了解这个组件。
下面将从三个方面分析:1、ContentProvider的加载;2、ContentProvider的调用;3、内容监听机制
1、来看看ContentProvider的加载过程,这个组件必须要在manifest文件中注册,这是有原因的,因为应用程序在安装过程中,这个组件的信息就应该被记录下来,以便在应用进程启动时就能直接根据组件信息来创建实例。
这个过程又跟系统的四大关键东西的功能,ActivityManagerService,PackageManagerService,ActivityThread和ApplicationThread。它们的关系相信大家都有一定的了解,这里就不阐述了。
下面从一个应用进程被创建说起。
在ActivityManagerService中,做一些诸如启动界面啊,广播啊,启动服务啊等等需要开始一个新的进程时就会执行到其中的startProcessLocked方法。有一行关键代码
</pre><pre name="code" class="html">Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, null, null);

意思就是说启动一个新进程,并且这个进程的入口是ActivityThread,那么其实对于应用程序来说ActivityThread.main才是它的入口,而并不是我们常说的组件之类的。
继续看main方法:
    public static void main(String[] args) {  
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        AsyncTask.init();
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");  
  }


这里面建立了主线程的handler和looper当然还有消息队列了,建立起了消息循环机制,所有的主线程操作全部都是在这里进行的。继续看attach操作
private void attach(boolean system) {
    if (!system) {
             IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
        }
}


又到ActivityManagerService里面去了,接下来就是一系列的方法调用了,还是长话短说吧,几经波折之后到了ApplicationThread的以下方法中
public final void bindApplication(String processName,
                ApplicationInfo appInfo, List<ProviderInfo> providers,
                ComponentName instrumentationName, String profileFile,
                ParcelFileDescriptor profileFd, boolean autoStopProfiler,
                Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
                int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode,
                boolean persistent, Configuration config, CompatibilityInfo compatInfo,
                Map<String, IBinder> services, Bundle coreSettings) {
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            ......
            //将app的provider信息传到ActivityThread的H中处理
            queueOrSendMessage(H.BIND_APPLICATION, data);
}
private class H extends Handler {
    public void handleMessage(Message msg) {
               switch (msg.what) {
               case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
    }
}
private void handleBindApplication(AppBindData data) {
            //前面一堆
            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                List<ProviderInfo> providers = data.providers;
                if (providers != null) {
                    installContentProviders(app, providers);
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }
           //后面还有Application的OnCreate等操作。
}


关于ContentProvider的重点来了,installContentProviders(app, providers);顾名思义这个里面就把Provider安装到系统中了,这其中包括了创建和注册两步,创建是一个在本进程内创建provider实例并保存,注册其实就是将这个provider在activitymanagerservice保存的过程。来看看具体的代码实现
    private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
        final ArrayList<IActivityManager.ContentProviderHolder> results =
            new ArrayList<IActivityManager.ContentProviderHolder>();
        for (ProviderInfo cpi : providers) {
            //创建provider实例
            IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
            if (cph != null) {
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }
        try {
            //将此记录保存到ActivityManagerService中
            ActivityManagerNative.getDefault().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
        }
    }
    private IActivityManager.ContentProviderHolder installProvider(Context context,
            IActivityManager.ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
        ContentProvider localProvider = null;
        IContentProvider provider;
        ......
        if (holder == null || holder.provider == null) {
             try {
                final java.lang.ClassLoader cl = c.getClassLoader();
                //这里就new出了一个ContentProvider的实例
                localProvider = (ContentProvider)cl.
                    loadClass(info.name).newInstance();
                provider = localProvider.getIContentProvider();
                if (provider == null) {
                    return null;
                }                // XXX Need to create the correct context for this provider.
                localProvider.attachInfo(c, info);
            }
          } else {
            provider = holder.provider;
            if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
                    + info.name);
          }
            ......
           synchronized (mProviderMap) {
            IBinder jBinder = provider.asBinder();
            if (localProvider != null) {
                ComponentName cname = new ComponentName(info.packageName, info.name);
                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
                if (pr != null) {
                    provider = pr.mProvider;
                } else {
                    holder = new IActivityManager.ContentProviderHolder(info);
                    holder.provider = provider;
                    holder.noReleaseNeeded = true;
                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                    //上面这个方法中将provider的信息保存在了mProviderMap中。
                    mLocalProviders.put(jBinder, pr);
                    mLocalProvidersByName.put(cname, pr);
                }
                retHolder = pr.mHolder;
            }
           }
        }
    }
    private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
            ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
        final String auths[] = PATTERN_SEMICOLON.split(holder.info.authority);
        final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
        final ProviderClientRecord pcr = new ProviderClientRecord(
                auths, provider, localProvider, holder);
        for (String auth : auths) {
            final ProviderKey key = new ProviderKey(auth, userId);
            final ProviderClientRecord existing = mProviderMap.get(key);
            if (existing != null) {
            } else {
                mProviderMap.put(key, pcr);
            }
        }
        return pcr;
    }


看到上面这里,可能大家都会有疑问,为什么这里有三个map来保存provider信息呢?这三个有什么区别什么时候使用这个目前还看不出来,后面的分析可能会看到一些端倪。我们下文将继续分析。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值