网站帮助文档怎么写,全国市场主体登记注册服务网,开商城网站多少钱,搜索引擎是什么意思1、ContentProvider介绍
ContentProvider主要用于向外部提供数据 1、自己应用进程提供数据
2、其它app进程的提供数据
这里分析本进程的ContentProvider的启动过程 2、ContentProvider启动分析
1、我们知道Android程序入口在ActivityThread.java文件的main函数里面#xf…1、ContentProvider介绍
ContentProvider主要用于向外部提供数据 1、自己应用进程提供数据
2、其它app进程的提供数据
这里分析本进程的ContentProvider的启动过程 2、ContentProvider启动分析
1、我们知道Android程序入口在ActivityThread.java文件的main函数里面如下代码 public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ActivityThreadMain);SamplingProfilerIntegration.start();// CloseGuard defaults to true and can be quite spammy. We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Set the reporter for event logging in libcoreEventLogger.setReporter(new EventLoggingReporter());AndroidKeyStoreProvider.install();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);Process.setArgV0(pre-initialized);Looper.prepareMainLooper();ActivityThread thread new ActivityThread();thread.attach(false);if (sMainThreadHandler null) {sMainThreadHandler thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, ActivityThread));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException(Main thread loop unexpectedly exited);} 2、我们这里可以看到有关键函数thread.attach(false)方法我们跟踪进去attach部分方法如下 private void attach(boolean system) {sCurrentActivityThread this;mSystemThread system;if (!system) {ViewRootImpl.addFirstDrawHandler(new Runnable() {Overridepublic void run() {ensureJitEnabled();}});android.ddm.DdmHandleAppName.setAppName(pre-initialized,UserHandle.myUserId());RuntimeInit.setApplicationObject(mAppThread.asBinder());final IActivityManager mgr ActivityManagerNative.getDefault();try {mgr.attachApplication(mAppThread);} catch (RemoteException ex) {// Ignore}// Watch for getting close to heap limit.BinderInternal.addGcWatcher(new Runnable() {Override public void run() {if (!mSomeActivitiesChanged) {return;}Runtime runtime Runtime.getRuntime();long dalvikMax runtime.maxMemory();long dalvikUsed runtime.totalMemory() - runtime.freeMemory();if (dalvikUsed ((3*dalvikMax)/4)) {if (DEBUG_MEMORY_TRIM) Slog.d(TAG, Dalvik max (dalvikMax/1024) total (runtime.totalMemory()/1024) used (dalvikUsed/1024));mSomeActivitiesChanged false;try {mgr.releaseSomeActivities(mAppThread);} catch (RemoteException e) {}}}});
******* 3、这里有个关键方法mgr.attachApplication(mAppThread)我们看下这个方法ActivityManagerService.java文件里面的实现 Overridepublic final void attachApplication(IApplicationThread thread) {synchronized (this) {int callingPid Binder.getCallingPid();final long origId Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid);Binder.restoreCallingIdentity(origId);}} 4、我们再看关键函数attachApplicationLocked函数部分实现 private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {*******boolean normalMode mProcessesReady || isAllowedWhileBooting(app.info);ListProviderInfo providers normalMode ? generateApplicationProvidersLocked(app) : null;*******thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(mConfiguration), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked());updateLruProcessLocked(app, false, null);app.lastRequestedGc app.lastLowMemory SystemClock.uptimeMillis(); 5、这里又调用了generateApplicationProvidersLocked(app)函数这个函数返回了一个ProviderInfo对象的集合我们跟踪这个函数看是如何得到这个集合的。 private final ListProviderInfo generateApplicationProvidersLocked(ProcessRecord app) {ListProviderInfo providers null;try {ParceledListSliceProviderInfo slice AppGlobals.getPackageManager().queryContentProviders(app.processName, app.uid,STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);providers slice ! null ? slice.getList() : null;} catch (RemoteException ex) {}if (DEBUG_MU) Slog.v(TAG_MU,generateApplicationProvidersLocked, app.info.uid app.uid);int userId app.userId;if (providers ! null) {int N providers.size();app.pubProviders.ensureCapacity(N app.pubProviders.size());for (int i0; iN; i) {ProviderInfo cpi (ProviderInfo)providers.get(i);boolean singleton isSingleton(cpi.processName, cpi.applicationInfo,cpi.name, cpi.flags);if (singleton UserHandle.getUserId(app.uid) ! UserHandle.USER_OWNER) {providers.remove(i);N--;i--;continue;}ComponentName comp new ComponentName(cpi.packageName, cpi.name);ContentProviderRecord cpr mProviderMap.getProviderByClass(comp, userId);if (cpr null) {cpr new ContentProviderRecord(this, cpi, app.info, comp, singleton);mProviderMap.putProviderByClass(comp, cpr);}if (DEBUG_MU) Slog.v(TAG_MU,generateApplicationProvidersLocked, cpi.uid cpr.uid);app.pubProviders.put(cpi.name, cpr);if (!cpi.multiprocess || !android.equals(cpi.packageName)) {app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.versionCode,mProcessStats);}ensurePackageDexOpt(cpi.applicationInfo.packageName);}}return providers;} 这里很明显是查询ContentProvider通过app进程名字和app的uid,然后得到一个ProviderInfo的集合就是这里的providers,然后我们遍历这个集合通过每个ProviderInfo的packageName和name属性构建ComponentName这个对象然后再去构建ContentProviderRecord对象key为ComponentName,value为ContentProviderRecord添加到这个ProviderMap对象里面也就是这行代码
mProviderMap.putProviderByClass(comp, cpr);
然后把返回的providers作为参数传递给了bindApplication函数。 6、我们看下bindApplication函数的实现在ActivityThread.java文件里面看下实现 public final void bindApplication(String processName, ApplicationInfo appInfo,ListProviderInfo providers, ComponentName instrumentationName,ProfilerInfo profilerInfo, Bundle instrumentationArgs,IInstrumentationWatcher instrumentationWatcher,IUiAutomationConnection instrumentationUiConnection, int debugMode,boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,Configuration config, CompatibilityInfo compatInfo, MapString, IBinder services,Bundle coreSettings) {AppBindData data new AppBindData();data.processName processName;data.appInfo appInfo;data.providers providers;data.instrumentationName instrumentationName;data.instrumentationArgs instrumentationArgs;data.instrumentationWatcher instrumentationWatcher;data.instrumentationUiAutomationConnection instrumentationUiConnection;data.debugMode debugMode;data.enableOpenGlTrace enableOpenGlTrace;data.restrictedBackupMode isRestrictedBackupMode;data.persistent persistent;data.config config;data.compatInfo compatInfo;data.initProfilerInfo profilerInfo;sendMessage(H.BIND_APPLICATION, data);}
我们可以看到发了一个携带providers数据的消息消息是H.BIND_APPLICATIONhandler类里面的handleMessage方法里面的收到消息处理如下 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;
很明显会调用handleBindApplication(data)方法。 7、我们看下handleBindApplication(data)方法部分实现 try {// If the app is being launched for full backup or restore, bring it up in// a restricted environment with the base application class.Application app data.info.makeApplication(data.restrictedBackupMode, null);mInitialApplication app;// dont bring up providers in restricted mode; they may depend on the// apps custom Application classif (!data.restrictedBackupMode) {ListProviderInfo 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);}}// Do this after providers, since instrumentation tests generally start their// test thread at this point, and we dont want that racing.try {mInstrumentation.onCreate(data.instrumentationArgs);}catch (Exception e) {throw new RuntimeException(Exception thrown in onCreate() of data.instrumentationName : e.toString(), e);}try {mInstrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!mInstrumentation.onException(app, e)) {throw new RuntimeException(Unable to create application app.getClass().getName() : e.toString(), e);}}} finally {StrictMode.setThreadPolicy(savedPolicy);}
这里为什么我要说明下面这行函数呢因为我们可以跟踪makeApplication函数里面去会调用我们平时代码里面继承了Application类的attachBaseContext函数这是我们一般app的Application类首先执行的函数
Application app data.info.makeApplication(data.restrictedBackupMode, null);
我们来跟踪下makeApplication函数传递的第二个参数是null,也就是Instrumentation传递进去是null,这里的data.info对象是LoadedApk对象,所以我们需要到这个LoadedApk.java文件里面来看这个函数的部分实现如下 public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {if (mApplication ! null) {return mApplication;}Application app null;String appClass mApplicationInfo.className;if (forceDefaultAppClass || (appClass null)) {appClass android.app.Application;}try {java.lang.ClassLoader cl getClassLoader();if (!mPackageName.equals(android)) {initializeJavaContextClassLoader();}ContextImpl appContext ContextImpl.createAppContext(mActivityThread, this);app mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);appContext.setOuterContext(app);} catch (Exception e) {if (!mActivityThread.mInstrumentation.onException(app, e)) {throw new RuntimeException(Unable to instantiate application appClass : e.toString(), e);}}mActivityThread.mAllApplications.add(app);mApplication app;if (instrumentation ! null) {try {instrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!instrumentation.onException(app, e)) {throw new RuntimeException(Unable to create application app.getClass().getName() : e.toString(), e);}}}
因为Instrumentation传递进去的是null,所以我们不会执行 instrumentation.callApplicationOnCreate(app)方法也就是不会执行Application里面的onCreate方法我们再看下mActivityThread.mInstrumentation.newApplication这个方法在Instrumentation.java文件看这个函数实现 public Application newApplication(ClassLoader cl, String className, Context context)throws InstantiationException, IllegalAccessException, ClassNotFoundException {return newApplication(cl.loadClass(className), context);}
接着看newApplication函数实现如下 static public Application newApplication(Class? clazz, Context context)throws InstantiationException, IllegalAccessException, ClassNotFoundException {Application app (Application)clazz.newInstance();app.attach(context);return app;}
然后再看这个Application的attach函数如下 /* package */ final void attach(Context context) {attachBaseContext(context);mLoadedApk ContextImpl.getImpl(context).mPackageInfo;}
我们发现这里已经调用了我们平时见得很多在Application里面的attachBaseContext(context)方法 8、再来分析ContentProvider的调用,我们看下这个installContentProviders(app, providers)这个函数这里providers是携带过来的数据方法实现如下 private void installContentProviders(Context context, ListProviderInfo providers) {final ArrayListIActivityManager.ContentProviderHolder results new ArrayListIActivityManager.ContentProviderHolder();for (ProviderInfo cpi : providers) {if (DEBUG_PROVIDER) {StringBuilder buf new StringBuilder(128);buf.append(Pub );buf.append(cpi.authority);buf.append(: );buf.append(cpi.name);Log.i(TAG, buf.toString());}IActivityManager.ContentProviderHolder cph installProvider(context, null, cpi,false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);if (cph ! null) {cph.noReleaseNeeded true;results.add(cph);}}try {ActivityManagerNative.getDefault().publishContentProviders(getApplicationThread(), results);} catch (RemoteException ex) {}}
我们可以看到这里调用了installProvider函数我们看下这个函数的调用在ActivityThread.java文件里面 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) {if (DEBUG_PROVIDER || noisy) {Slog.d(TAG, Loading provider info.authority : info.name);}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 {c context.createPackageContext(ai.packageName,Context.CONTEXT_INCLUDE_CODE);} catch (PackageManager.NameNotFoundException e) {// Ignore}}if (c null) {Slog.w(TAG, Unable to get context for package ai.packageName while loading content provider info.name);return null;}try {final java.lang.ClassLoader cl c.getClassLoader();localProvider (ContentProvider)cl.loadClass(info.name).newInstance();provider localProvider.getIContentProvider();if (provider null) {Slog.e(TAG, Failed to instantiate class info.name from sourceDir info.applicationInfo.sourceDir);return null;}if (DEBUG_PROVIDER) Slog.v(TAG, Instantiating local provider info.name);// XXX Need to create the correct context for this provider.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;if (DEBUG_PROVIDER) Slog.v(TAG, Installing external provider info.authority : info.name);}
我们可以看到返回对象是IActivityManager.ContentProviderHolder然后这里先获取相应的Context上下文信息然后ClassLoader加载对应的ContentProvider类并创建该类的对象然后我们调用了如下函数参数是上下文和函数传递进来的
ProviderInfo.
localProvider.attachInfo(c, info);
然后我们跟踪这个函数到里面去(在ContentProvider类文件里面)代码如下 public void attachInfo(Context context, ProviderInfo info) {attachInfo(context, info, false);}
继续跟踪这个函数attachInfo函数 private void attachInfo(Context context, ProviderInfo info, boolean testing) {mNoPerms testing;/** Only allow it to be set once, so after the content service gives* this to us clients cant change it.*/if (mContext null) {mContext context;if (context ! null) {mTransport.mAppOpsManager (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);}mMyUid Process.myUid();if (info ! null) {setReadPermission(info.readPermission);setWritePermission(info.writePermission);setPathPermissions(info.pathPermissions);mExported info.exported;mSingleUser (info.flags ProviderInfo.FLAG_SINGLE_USER) ! 0;setAuthorities(info.authority);}ContentProvider.this.onCreate();}}
很明显这里调用的ContentProvider的onCreate函数也就是我们平时见到的继承ContentProvider类的onCreate函数这里ContentProvider就创建完了。
然后installProvider方法还有部分如下 IActivityManager.ContentProviderHolder retHolder;synchronized (mProviderMap) {if (DEBUG_PROVIDER) Slog.v(TAG, Checking to add provider / info.name);IBinder jBinder provider.asBinder();if (localProvider ! null) {ComponentName cname new ComponentName(info.packageName, info.name);ProviderClientRecord pr mLocalProvidersByName.get(cname);if (pr ! null) {if (DEBUG_PROVIDER) {Slog.v(TAG, installProvider: lost the race, using existing local provider);}provider pr.mProvider;} else {holder new IActivityManager.ContentProviderHolder(info);holder.provider provider;holder.noReleaseNeeded true;pr installProviderAuthoritiesLocked(provider, localProvider, holder);mLocalProviders.put(jBinder, pr);mLocalProvidersByName.put(cname, pr);}retHolder pr.mHolder;} else {ProviderRefCount prc mProviderRefCountMap.get(jBinder);if (prc ! null) {if (DEBUG_PROVIDER) {Slog.v(TAG, installProvider: lost the race, updating ref count);}// We need to transfer our new reference to the existing// ref count, releasing the old one... but only if// release is needed (that is, it is not running in the// system process).if (!noReleaseNeeded) {incProviderRefLocked(prc, stable);try {ActivityManagerNative.getDefault().removeContentProvider(holder.connection, stable);} catch (RemoteException e) {//do nothing content provider object is dead any way}}} else {ProviderClientRecord client installProviderAuthoritiesLocked(provider, localProvider, holder);if (noReleaseNeeded) {prc new ProviderRefCount(holder, client, 1000, 1000);} else {prc stable? new ProviderRefCount(holder, client, 1, 0): new ProviderRefCount(holder, client, 0, 1);}mProviderRefCountMap.put(jBinder, prc);}retHolder prc.holder;}}return retHolder;}获取ContetProvider的IContentProvider赋值给provider变量,然后调用
IBinder jBinder provider.asBinder();
IContentProvider可以理解为ContentProvider客户端和服务端通信的接口这里根据ProviderInfo的信息和Binder类型IContentProvider对象创建一个ContentProviderHolder对象它里边封装了这个ContentProvider的ProviderInfo和IContentProvider信息然后又调用了下面的方法我们跟踪进去 private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {final String auths[] holder.info.authority.split(;);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) {Slog.w(TAG, Content provider pcr.mHolder.info.name already published as auth);} else {mProviderMap.put(key, pcr);}}return pcr;}
然后这里根据Provider的信息构造了ProviderClientRecord对象authority是一个多属性值变量这个Provider对应的所有authority,每个authority属性为key,保存这个ProviderClientReocrd到mProviderMap的HashMap中
我们可以看下这个地方本地声明的缓存存储信息在ActivityThread.java这个类文件中 // The lock of mProviderMap protects the following variables.final ArrayMapProviderKey, ProviderClientRecord mProviderMap new ArrayMapProviderKey, ProviderClientRecord();final ArrayMapIBinder, ProviderRefCount mProviderRefCountMap new ArrayMapIBinder, ProviderRefCount();final ArrayMapIBinder, ProviderClientRecord mLocalProviders new ArrayMapIBinder, ProviderClientRecord();final ArrayMapComponentName, ProviderClientRecord mLocalProvidersByName new ArrayMapComponentName, ProviderClientRecord();
通过不同的key来存储然后构建不同的map对象分别是以authority为key、IBinder文key、ComponentName为key.
代码后面还按照其它方式保存到内存 mLocalProviders.put(jBinder, pr);mLocalProvidersByName.put(cname, pr);
按照不同的存储类型分别保存不同的ContentProvider集合中。
然后我们在第8步开始的installContentProviders方法里面还有这个函数没有分析publishContentProviders函数代码实现如下 public final void publishContentProviders(IApplicationThread caller,ListContentProviderHolder providers) {if (providers null) {return;}enforceNotIsolatedCaller(publishContentProviders);synchronized (this) {final ProcessRecord r getRecordForAppLocked(caller);if (DEBUG_MU) Slog.v(TAG_MU, ProcessRecord uid r.uid);if (r null) {throw new SecurityException(Unable to find app for caller caller (pid Binder.getCallingPid() ) when publishing content providers);}final long origId Binder.clearCallingIdentity();final int N providers.size();for (int i0; iN; i) {ContentProviderHolder src providers.get(i);if (src null || src.info null || src.provider null) {continue;}ContentProviderRecord dst r.pubProviders.get(src.info.name);if (DEBUG_MU) Slog.v(TAG_MU, ContentProviderRecord uid dst.uid);if (dst ! null) {ComponentName comp new ComponentName(dst.info.packageName, dst.info.name);mProviderMap.putProviderByClass(comp, dst);String names[] dst.info.authority.split(;);for (int j 0; j names.length; j) {mProviderMap.putProviderByName(names[j], dst);}int NL mLaunchingProviders.size();int j;for (j0; jNL; j) {if (mLaunchingProviders.get(j) dst) {mLaunchingProviders.remove(j);j--;NL--;}}synchronized (dst) {dst.provider src.provider;dst.proc r;dst.notifyAll();}updateOomAdjLocked(r);maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,src.info.authority);}}Binder.restoreCallingIdentity(origId);}}为每一个ContentProvider信息创建了一个ContentProviderRecord对象保存到了ProviderMap集合中,启动的ContentProvider按照authority为key保存到ProviderMap中这里工作主要就是将ContentProvider的信息保存到AMS服务中去。
AMS服务保存ContentProvider的信息主要是在类ProviderMap中它里边有两种保存的Provider信息的集合 1. ProviderByClass 以ComponentName为key保存了ContentProviderRecord的信息 2. ProviderByName 以authority为key保存了ContentProviderRecord的信息 最后我们不是看到这个函数
notifyAll() 不同进程间调用ContentProvider的时候先会判断该ContentProvider所在的进程是否已经启动如果有启动需要首先启动该进程在该进程启动完成后这个ContentProvider也就启动起来了比如在我们项目中我们有2个进程然后一个ContentProvider在一个进程里面我们在自己app通过下面的方法拉起ContentProvider getContentResolver().insert
如果没有启动的时候AMS就会首先启动个进程及ContentProvider并把这个ContentProviderRecord添加到等待队列mLaunchingProviders中去如下声明 final ArrayListContentProviderRecord mLaunchingProviders new ArrayListContentProviderRecord();然后等他它启动完成此处代码就是新的进程及ContentProvider启动完成后首先判断是否在等待进程中如果有就将该ContentProvider信息从等待队列中移除并调用notifyAll来唤醒等待的工作。 9、最后分析handleBindApplication函数的最后一步 final StrictMode.ThreadPolicy savedPolicy StrictMode.allowThreadDiskWrites();try {// If the app is being launched for full backup or restore, bring it up in// a restricted environment with the base application class.Application app data.info.makeApplication(data.restrictedBackupMode, null);mInitialApplication app;// dont bring up providers in restricted mode; they may depend on the// apps custom Application classif (!data.restrictedBackupMode) {ListProviderInfo 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);}}// Do this after providers, since instrumentation tests generally start their// test thread at this point, and we dont want that racing.try {mInstrumentation.onCreate(data.instrumentationArgs);}catch (Exception e) {throw new RuntimeException(Exception thrown in onCreate() of data.instrumentationName : e.toString(), e);}try {mInstrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!mInstrumentation.onException(app, e)) {throw new RuntimeException(Unable to create application app.getClass().getName() : e.toString(), e);}}} finally {StrictMode.setThreadPolicy(savedPolicy);}
当有触发ContentProvider启动完成的时候我们可以看到才去执行 mInstrumentation.callApplicationOnCreate(app);
这里跟踪进去也就是Application的onCreate方法所以它是在ContentProvider的onCreate后面(前提是同时启动Appliation和ContentProvider) 3、总结
AMS服务保存ContentProvider的信息主要是在类ProviderMap中它里边有两种保存的Provider信息的集合 1. ProviderByClass 以ComponentName为key保存了ContentProviderRecord的信息 2. ProviderByName
以authority为key保存了ContentProviderRecord的信息
3、如果Applicaton和ContentProvider都会起来确保ContentProvider在本进程里面不能单独开辟一个进程放ContentProvider,那么部分函数执行顺序如下
Application继承类的的attachBaseContext方法-----ContentProvider继承类的onCreate方法----pplication继承类的onCreate函数
4、如果是Applicaton和ContentProvider不在同进程不管是否在一个app里面的不同进程还是在另外一个app的进程那么会先启动Application继承类的的attachBaseContext方法-----Application继承类的onCreate函数,如果有另外一个进程或者一个app触发ContentProvider,那么依然部分函数执行顺序如下
Application继承类的的attachBaseContext方法-----ContentProvider继承类的onCreate方法----pplication继承类的onCreate函数,因为每个进程都有一个Application所以会在ContentProvider里面再次启动一次Application