First, preface
ContentProvider as one of the four components of Android, assume the role of data storage, this article with a most typical deletion (delete) operation, according to the Android source code,
from the application layer of the Getcontentresolver (), step-by-step analysis to the internal ContentProvider, the final operation to reach SQLite。
[Java]View plain copy getcontentresolver (). Delete (); This simple operation actually consists of two steps:
1, through Getcontentresolver () to obtain the required ContentProvider object;
2, through the Delete () operation, the data in the ContentProvider is deleted;
Let's start this long journey.
Second, Getcontentresolver look at the title, we are to get a Contentresolver object, which produced two questions:
1, Contentresolver object and ContentProvider have what relationship.
2. How did we get the content in ContentProvider?
To answer these two questions, we need to start with the analysis at the source of the code:
2.1. The relationship between Contentresolver and ContentProviderLet's take a look at the process of getting contentresolver:[Java]View plain copy @ContextImpl. Java public contentresolver Getcontentresolver () {return mcontentresolver; The mcontentresolver here is initialized in the Contextimpl init:
[Java]View plain copy final void init (resources resources, Activitythread Mainthread, Userhandle user) {Mpackageinfo = Nu ll Mbasepackagename = null; Mresources = resources; Mmainthread = Mainthread; Mcontentresolver is initialized to Applicationcontentresolver object mcontentresolver = new Applicationcontentresolver (This, mainThr EAD, user); Muser = user; } Mcontentresolver is initialized to Applicationcontentresolver object, let's look at Applicationcontentresolver this class, he is Contextimpl's inner class:[Java] View Plain Copy private static final class applicationcontentresolver extends contentresolver { public applicationcontentresolver ( Context context, activitythread mainthread, userhandle user) { } protected icontentprovider acquireprovider (context context, string Auth) { } protected IContentProvider Acquireexistingprovider (Context context, string auth) { } public boolean releaseprovider (Icontentprovider provider) { } protected icontentprovider acquireunstableprovider (Context c, String auth) { } public boolean Releaseunstableprovider (ICONTENTPROVIDER ICP) { } public void unstableproviderdied (icontentprovider  ICP) { } } He offers a variety of ways to get Icontentprovider, And inheriting from the Contentresolver class, let's look at the properties of this class:[Java]View plain copy @ContentResolver. Java public abstract class Contentresolver {} You can see that contentresolver does not inherit any classes or interface, so that we can think thatin terms of inheritance, Contentresolver has nothing to do with ContentProvider.。
So how did we finally get contentprovider?
2.2, how to get ContentProvider through ContentresolverLet's answer the second question, we areHow to query the contents of ContentProvider through Contentresolver.
Although we know that there is no connection between the two in terms of inheritance, there are a number of methods that we are familiar with in the interior of Contentresolver, including:[Java]View Plain copy public final Cursor query (Uri uri, string[] projection, string selection, string[] Selectionargs, string s Ortorder) {} public final int delete (URI URL, String where, string[] Selectionargs) {} public final int update (URI Uri, Contentvalues values, String where, string[] Selectionargs) {} public final Uri insert (URI URL, contentvalues values) {} This shows that there must be a link between the two functions, and below we analyze from the very beginning of the delete operation to see what the relationship is.
Back to the original call location, when we need to delete a piece of data through ContentProvider, we call Getcontentresolver (). Delete () method, which analyzes the word,Getcontentresolver () gets the Applicationcontentresolver object., and Applicationcontentresolver inherits from Contentresolver. Therefore, the delete operation falls into the Contentresolver:[Java]View plain copy @ContentResolver. java Public final int delete (Uri URL, String where, string[] selectionargs) {I ContentProvider Provider = acquireprovider (URL); try {int rowsdeleted = provider.delete (URL, where, Selectionargs); } catch (RemoteException e) {} finally {}} In this step, we first get the Icontentprovider object by Acquireprovider () and then Operate with the Delete method of the Icontentprovider object. So, here's how to get the Icontentprovider object through Acquireprovider ().[Java]View Plain copy public final Icontentprovider Acquireprovider (Uri uri) {//Secure confirm if (! Scheme_content.equals (Uri.getscheme ())) {return null; } final String auth = uri.getauthority (); if (auth! = null) {//continues to call return Acquireprovider (Mcontext, auth); } return null; } Continue to look at:[Java]View plain copy protected abstract Icontentprovider Acquireprovider (Context C, String name); There is an abstract acquireprovider here, which shows that this method needs to be implemented in subclasses, then we go to Applicationcontentresolver to see:[Java]View plain copy @ContextImpl. Java private static final class Applicationcontentresolver extends Contentresolver { Sure enough, I found the Acquireprovider method protected Icontentprovider Acquireprovider (context context, String auth) {return Mmainthread.acquireprovider (context, Auth, Muser.getidentifier (), true); }} We did find the Acquireprovider () method in the Applicationcontentresolver and foundThe return value provided by the Acquireprovider method is the Acquireprovider method from the Mmainthread object。
So, where does this mmainthread come from?
The following procedure is more complicated, you are optimistic.
2.3, look for Mmainthread object OriginAfter an activity is created in Activitythread, the Createbasecontextforactivity () method in Activitythread is called. Create a context object and a Mmainthread object for the current activity:[Java]View plain copy @ActivityThread. Java Private Context createbasecontextforactivity (Activityclientrecord R, Final Activit Y activity) {//here is where you want to create the context object Contextimpl AppContext = new Contextimpl (); and pass the current Activitythread object to Contextimpl's Init method Appcontext.init (R.packageinfo, R.token, this); This will call the Init method in Contextimpl:[Java] View Plain copy @ContextImpl .java //The mainthread here is Activitythread object final void Init (loadedapk packageinfo, ibinder activitytoken, activitythread mainthread) { init (packageinfo, activitytoken, mainthread, null, Null, process.myuserhandle ()); } Final void init (LoadedApk packageinfo, ibinder activitytoken, activitythread mainthread, resources Container, string basepackagename, userhandle user) { // Mmainthread is Activitythread object mMainThread = mainThread; mcontentresolver = new applicationcontentresolver (this, Mainthread, user); } This process we found thatMmainthread is the Activitythread object ., so the Mmainthread.acquireprovider () we introduced in 2.2 is equivalent to:[Java]View plain copy Activitythread.acquireprovider (); We continue to look at:[Java] View plain copy @ActivityThread .java Public final icontentprovider acquireprovider ( context c, string auth, int userid, boolean stable) { final icontentprovider provider = acquireexistingprovider (c, auth, userid, stable); if (provider != null) { return provider; } iactivitymanager.contentproviderholder holder = null; try { holder = activitymanagernative.getdefault (). GetContentProvider ( Getapplicationthread (), auth, userid, stable); } catch (RemoteexceptiOn ex) { } holder = installprovider (c, holder, holder.info, true , holder.noreleaseneeded, stable); return holder.provider; } Here you can see thatthere is a hashmap in Activitythread to cache all provider. Each request to provider is first passed through the Acquireexistingprovider () query whether it has been cached, and if there is no cache, to create the Contentproviderholder object of the provider. Cached at the same time to facilitate the next call。
We assume that there is currently no Contactsprovider cache, then the provider will be created through Activitymanagernative.getdefault (). Getcontentprovider (). Let's analyze the process of this creation.
2.4, Activitythread the process of creating contentprovider. as mentioned earlier, Activitythread created ContentProvider is implemented in the following way: [Java] view plain copy activitymanagernative.getdef Ault (). Getcontentprovider (Getapplicationthread (), auth, userId, stable);
This process can be divided into two steps:
1. We look at the objects obtained through Activitymanagernative.getdefault ();
2. We'll analyze the Getcontentprovider method of this object again .。2.4.1, Activitymanagernative object. Let's introduce the Activitymanagerservice service first.
When the system starts, some important servers are started up in Systemserver, including Activitymanagerservice:[Java]View plain copy @SystemServer. Java public void Run () {//start activitymanagerservice context = Activitymanagers Ervice.main (factorytest); Registered Activitymanagerservice activitymanagerservice.setsystemprocess (); The result of calling the Activitymanagerservice.main method above is to start Activitymanagerservice, and then call setsystemprocess to register activitymanagerservice to the system Ec[Java] View plain copy @ActivityManagerService .java public static void setsystemprocess () { try { ActivityManagerService m = mSelf; //to register himself as an "activity" server servicemanager.addservice ("activity", m, true) ; servicemanager.addservice ("Meminfo", new membinder (m)); servicemanager.addservice (" Gfxinfo ", new graphicsbinder (m)); Servicemanager.addservice ("Dbinfo", new dbbinder (m)); } catch (Packagemanager. namenotfoundexception e) { } } We'll look at Activitymanagerservice's inheritance:[Java]View Plain Copy <