Android内容提供者(ContentProvider)浅析(一)
2014-06-14 12:15
369 查看
ContentProvider是Android系统四大基本组件中涉及到数据共享的重要角色。本文将对它的一些知识做一些简介来引导大家更好的了解这个组件。
下面将从三个方面分析:1、ContentProvider的加载;2、ContentProvider的调用;3、内容监听机制
1、来看看ContentProvider的加载过程,这个组件必须要在manifest文件中注册,这是有原因的,因为应用程序在安装过程中,这个组件的信息就应该被记录下来,以便在应用进程启动时就能直接根据组件信息来创建实例。
这个过程又跟系统的四大关键东西的功能,ActivityManagerService,PackageManagerService,ActivityThread和ApplicationThread。它们的关系相信大家都有一定的了解,这里就不阐述了。
下面从一个应用进程被创建说起。
在ActivityManagerService中,做一些诸如启动界面啊,广播啊,启动服务啊等等需要开始一个新的进程时就会执行到其中的startProcessLocked方法。有一行关键代码
意思就是说启动一个新进程,并且这个进程的入口是ActivityThread,那么其实对于应用程序来说ActivityThread.main才是它的入口,而并不是我们常说的组件之类的。
继续看main方法:
这里面建立了主线程的handler和looper当然还有消息队列了,建立起了消息循环机制,所有的主线程操作全部都是在这里进行的。继续看attach操作
又到ActivityManagerService里面去了,接下来就是一系列的方法调用了,还是长话短说吧,几经波折之后到了ApplicationThread的以下方法中
关于ContentProvider的重点来了,installContentProviders(app, providers);顾名思义这个里面就把Provider安装到系统中了,这其中包括了创建和注册两步,创建是一个在本进程内创建provider实例并保存,注册其实就是将这个provider在activitymanagerservice保存的过程。来看看具体的代码实现
看到上面这里,可能大家都会有疑问,为什么这里有三个map来保存provider信息呢?这三个有什么区别什么时候使用这个目前还看不出来,后面的分析可能会看到一些端倪。我们下文将继续分析。
下面将从三个方面分析: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信息呢?这三个有什么区别什么时候使用这个目前还看不出来,后面的分析可能会看到一些端倪。我们下文将继续分析。
相关文章推荐
- Android内容提供者(ContentProvider)浅析(二)
- Android内容提供者(ContentProvider)浅析(三)
- Android开发13――内容提供者ContentProvider的基本使用
- Android ContentProvider 内容提供者
- Android学习---通过内容提供者(ContentProvider)操作另外一个应用私有数据库的内容
- android内容提供者ContentProvider
- Android开发14——监听内容提供者ContentProvider的数据变化
- [Android Pro] 监听内容提供者ContentProvider的数据变化
- Android开发之ContentProvider(内容提供者)
- Android开发13——内容提供者ContentProvider的基本使用 推荐
- Android开发13——内容提供者ContentProvider的基本使用
- Android -- ContentProvider 内容提供者,创建和调用
- Android开发14――监听内容提供者ContentProvider的数据变化
- Android 使用ContentProvider(内容提供者)共享数据
- Android ContentProvider(内容提供者)
- Android开发14——监听内容提供者ContentProvider的数据变化
- Android四大组件之一ContentProvider(内容提供者)
- Android--- ContentProvider(内容提供者)
- Android中内容提供者ContentProvider实现数据库增删改查
- Android开发14——监听内容提供者ContentProvider的数据变化