This article refers to the principles of the Android application component content provider sharing data between applications http://blog.csdn.net/luoshengyang/article/details/6967204 and the Android System source code scenario analysis, author Luo Shenyang.
0, the general diagram flowchart is as follows:
Overall class Diagram:
1. Mainactivity process sends icontentprovider.query_transaction to Ariticlesprovider process
The first step
~/android/frameworks/base/core/java/android/content
----Contentprovidernative.java
Final class Contentproviderproxy implements Icontentprovider {... public Cursor query (Uri URL, string[] projection, Str ing selection,string[] selectionargs, String sortOrder) throws RemoteException {//todo make a pool of windows so we can re Use memory dealerscursorwindow window = new Cursorwindow (false/* window would be used remotely */); Bulkcursortocursoradaptor adaptor = new Bulkcursortocursoradaptor (); Ibulkcursor bulkcursor = bulkqueryinternal (URL, Projection, selection, Selectionargs, Sortorder,adaptor.getobserver (), window,adaptor); if (bulkcursor = = null) {return null;} return adaptor;} ......
(1) The Cursorwindow object is created.
(2) Create a class Bulkcursortocursoradaptor object.
(3) Call bulkqueryinternal.
~/android/frameworks/base/core/java/android/content
----Contentprovidernative.java
Final class Contentproviderproxy implements Icontentprovider{......private ibulkcursor bulkqueryinternal (Uri URL, String[] projection,string selection, string[] Selectionargs, String sortorder,icontentobserver Observer, Cursorwindow Window,bulkcursortocursoradaptor adaptor) throws RemoteException {Parcel data = Parcel.obtain (); Parcel reply = Parcel.obtain ();d Ata.writeinterfacetoken (icontentprovider.descriptor); url.writetoparcel (data, 0); int length = 0;if (projection! = null) {length = Projection.length;} Data.writeint (length); for (int i = 0; i < length; i++) {data.writestring (projection[i]);} Data.writestring (selection); if (Selectionargs! = null) {length = Selectionargs.length;} else {length = 0;} Data.writeint (length); for (int i = 0; i < length; i++) {data.writestring (selectionargs[i]);} Data.writestring (SortOrder);d Ata.writestrongbinder (Observer.asbinder ()); Window.writetoparcel (data, 0);//Flag for Whether or not we want the number of rows in the//cursor and the position of the "_ID "column index (or-1 if//non-existent). Only to is returned if binder! = null.final Boolean wantscursormetadata = (adaptor! = null);d Ata.writeint (Wantscursormetad Ata? 1:0); Mremote.transact (icontentprovider.query_transaction, data, reply, 0);D Atabaseutils.readexceptionfromparcel ( Reply); Ibulkcursor bulkcursor = Null;ibinder Bulkcursorbinder = Reply.readstrongbinder (); if (bulkcursorbinder! = null) { Bulkcursor = Bulkcursornative.asinterface (Bulkcursorbinder); if (wantscursormetadata) {int rowCount = Reply.readint (); int idcolumnposition = Reply.readint (); if (bulkcursor! = null) {Adaptor.set (Bulkcursor, RowCount, idcolumnposition);}}} Data.recycle (); reply.recycle (); return bulkcursor;} ......}We are only interested in Window.writetoparcel (data, 0). For a detailed explanation please see the corresponding blog or book.
The second step, omit the binder_transaction transfer process, because the above has been analyzed it's over.
Step Three
~/android/frameworks/base/core/java/android/content
----Contentprovidernative.java
Abstract public class Contentprovidernative extends Binder implements Icontentprovider {... @Overridepublic boolean Ontransact (int code, PARCEL data, Parcel reply, int flags) throws RemoteException {try {switch (code) {Case Query_transacti On:{data.enforceinterface (Icontentprovider.descriptor); Uri URL = Uri.CREATOR.createFromParcel (data);//string[] Projectionint num = Data.readint (); string[] projection = null;if (num > 0) {projection = new String[num];for (int i = 0; i < num; i++) {Projection[i] = Data.readstring ();}} String selection, string[] Selectionargs ... String selection = data.readstring (); num = Data.readint (); string[] Selectionargs = null;if (num > 0) {Selectionargs = new String[num];for (int i = 0; i < num; i++) {Selection Args[i] = data.readstring ();}} String SortOrder = data.readstring (); Icontentobserver observer = IContentObserver.Stub.asInterface ( Data.readstrongbinder ()); Cursorwindow window = CursorWindow.CREATOR.createFromParcel (data);//Flag for whether callEr wants the number of//rows in the cursor and the position of the//"_id" column index (or-1 if non-existent)//only to be returned if binder! = Null.boolean Wantscursormetadata = Data.readint ()! = 0;ibulkcursor bulkcursor = bulkquery (URL, p Rojection, Selection,selectionargs, SortOrder, observer, window); reply.writenoexception (); if (bulkcursor! = null) { Reply.writestrongbinder (Bulkcursor.asbinder ()); if (wantscursormetadata) {Reply.writeint (BulkCursor.count ()); Reply.writeint (Bulkcursortocursoradaptor.findrowidcolumnindex (Bulkcursor.getcolumnnames ()));}} else {reply.writestrongbinder (null);} return true;} ......}} catch (Exception e) {databaseutils.writeexceptiontoparcel (reply, E); return true;} Return Super.ontransact (Code, data, reply, flags);} ......}Among them, Cursorwindow window = CursorWindow.CREATOR.createFromParcel (data); Please read the blog or the book for detailed explanations.
Fourth Step
~/android/frameworks/base/core/java/android/content
----Contentprovider.java
Public abstract class ContentProvider implements Componentcallbacks {... class Transport extends contentprovidernative {... public ibulkcursor bulkquery (Uri Uri, string[] projection,string selection, string[] Selectionargs, String sortorder,icontentobserver Observer, Cursorwindow window) {... cursor cursor = ContentProvider.this.query (URI, Projection,selection, Selectionargs, SortOrder), ... return new Cursortobulkcursoradaptor (cursor, Observer,contentprovider.this.getclass (). GetName (), Haswritepermission (URI), window);} ......} ......}
The following are the main things to do:
(1) Call the Ariticlesprovider query method and get the Sqlitecursor object.
(2) A Cursortobulkcursoradaptor object is formed by the cursor and window objects.
, the fifth step
if (bulkcursor! = null) {Reply.writestrongbinder (Bulkcursor.asbinder ()), if (wantscursormetadata) {Reply.writeint ( Bulkcursor.count ()); Reply.writeint (Bulkcursortocursoradaptor.findrowidcolumnindex (BulkCursor.getColumnNames ()) );}}
Pass Cursortobulkcursoradaptor objects, such as:
Sixth step, omit the binder_transaction transmission process, because the above has been analyzed .
Seventh Step
~/android/frameworks/base/core/java/android/content
----Contentprovidernative.java
Ibulkcursor Bulkcursor = Null;ibinder Bulkcursorbinder = Reply.readstrongbinder (); if (bulkcursorbinder! = null) { Bulkcursor = Bulkcursornative.asinterface (Bulkcursorbinder); if (wantscursormetadata) {int rowCount = Reply.readint (); int idcolumnposition = Reply.readint (); if (bulkcursor! = null) {Adaptor.set (Bulkcursor, RowCount, idcolumnposition);}}}
Bulkcursor is the Bulkcursorproxy object as follows:
Adaptor.set (Bulkcursor, RowCount, idcolumnposition);
Put the Bulkcursorproxy object into the handle variable mbulkcursor of the Bulkcursortocursoradaptor object.
Eighth step
return new Cursorwrapperinner (qcursor, provider);
Finally, the object is returned, Qcursor isthe Bulkcursortocursoradaptor object, provider as the Contentproviderproxy object.
So far, we have formed:
interprocess communication is over, and below we analyze how to apply anonymous shared memory to transfer data .
In a previous article on Android Content provider the boot process source code Analysis http://blog.csdn.net/jltxgcy/article/details/ 37725749, finally obtains the Contentproviderproxy object, passes the data through the inter-process communication .
public class Articlesadapter {... private contentresolver resolver = Null;public Articlesadapter (context context) { Resolver = Context.getcontentresolver ();} ... public article getarticlebypos (int pos) {uri uri = Contenturis.withappendedid (Articles.content_pos_uri, POS); string[] projection = new string[] {articles.id,articles.title,articles.abstract,articles.url}; cursor cursor = resolver.query (URI, projection, null, NULL, Articles.default_sort_order), if (!cursor.movetofirst ()) { return null;} int id = cursor.getint (0); String title = cursor.getstring (1); String ABS = cursor.getstring (2); String url = cursor.getstring (3); return new article (ID, title, ABS, URL);}}
We do not analyze the detailed process, first bulkcursortocursoradaptor the member variables inside the object mbulkcursor through interprocess communication, find Cursortobulkcursoradaptor object, The data is queried through the member function mcursor inside, and the anonymous shared memory pointed to by Mwindows is saved.
Instead, Bulkcursortocursoradaptor accesses the same anonymous shared memory through the member variable Mwindow. This mainactivity gets the data.