1. What is ContentProvider
The content provider, a layer of abstraction for all data access, provides a unified interface for data access. It has the following advantages:
A. Abstraction of data, providing uniform access to data for all components so that components do not have to be concerned with the rendering of specific data (file or database). Data, you can also only care about your own management, without having to manage the user's access issues. This will achieve a good encapsulation.
B. Interface more convenient, more convenient to transfer data between components
ContentProvider access is identified as a URI, accessed through a unified contentresolver, And the Contentresolver and URI and the application context and the information transfer tool between the components intent seamless interface, which makes the data sharing and data transmission between the components more convenient and faster.
Therefore, the greatest benefit of contentprovider is that it can be easily shared among different components. So, if the data you use in your application needs to be shared among different components, then implementing a contentprovider is undoubtedly the best solution.
2. How to Achieve
ContentProvider implementation is very simple, just need to implement some interface according to the requirements, such as: query, INSERT, delete, UPDATE, OpenFile and so on. However, the presentation of the specific data is based on the different purposes of free choice, such as for structured data, select Sqlitedatabase may be a better solution, a large number of streams of bytes may be the preferred file is the first and so on.
It's important to note that while 90% of Android's ContentProvider internally use Sqlitedatabase to store structured data, But that does not mean that ContentProvider can only manage data from sqlitedatabase. ContentProvider defines some interfaces, and you just need to return the correct data as needed, and the specific implementation is free.
For example, Contacts's ContentProvider can provide a vcard output, meaning that when reading a vcard URI, the stream is a vcard-like file stream, and the idea is to do so:
Copy Code code as follows:
Cursor query (Uri, ...) {
If (URI is for VCard) {
Query the contact ' s infomation
Create a cursor with two columns name and size
Put contacts ' s name into cursor
Sum all contacts ' s field and get size
Put so size into cursor
Return the cursor
}
}
In this way, you can get the name and size of the relevant information file for this vcard through query, and then you can read the vcard file stream via Openinputstream, but in fact ContentProvider is not in the form of a vcard. There is also no vcard file, it is only when OpenFile, recognize the URI of the vcard, the contact data into a vcard to write to the output stream:
Copy Code code as follows:
Parcelfiledescriptor OpenFile (Uri ...) {
If (URI is for vcard) {
Generate vcard with Vcardcomposer
Write to output stream
}
}
3. Other alternative programmes
ContentProvider is not required, each application must use data, but you can choose to manage with creating a contentprovider, or you can use files or databases directly, as in the following example:
Copy Code code as follows:
Package com.android.effective;
Import android.app.Activity;
Import android.content.ContentValues;
Import Android.content.Context;
Import Android.database.Cursor;
Import Android.database.sqlite.SQLiteDatabase;
Import Android.database.sqlite.SQLiteOpenHelper;
Import Android.database.sqlite.SQLiteDatabase.CursorFactory;
Import Android.os.Bundle;
Import Android.util.Log;
public class Sqlitedatabasedemo extends activity {
private static final String TAG = "Sqlitedatabasedemo";
@Override
public void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
MyDatabase db = new MyDatabase (this);
int id = db.setname ("Michael Jordan");
LOG.E (TAG, "ID of" + ID + "is" + db.getname (ID));
}
Private class MyDatabase {
Private static final String name = "Demo.db";
Private static final String table = "Demo";
Private final string[] projection = new string[] {"_id", "name"};
Private Mydatabasehelper Helper;
Public MyDatabase {
Helper = new Mydatabasehelper (context, name, NULL, 1);
}
Public String getName (int id) {
Final Cursor C = helper.getreadabledatabase (). Query ("Demo", Projection, "_id=" + ID,
NULL, NULL, NULL, NULL);
if (c = = NULL | |!c.movetofirst ()) {
return null;
}
return c.getstring (1);
}
public int SetName (String name) {
Contentvalues CV = new Contentvalues ();
Cv.put ("name", name);
return (int) helper.getwritabledatabase (). Insert (table, "name", CV);
}
}
Private class Mydatabasehelper extends Sqliteopenhelper {
Public Mydatabasehelper (context, String name,
Cursorfactory Factory, int version) {
Super (context, name, Factory, version);
}
@Override
public void OnCreate (Sqlitedatabase db) {
Db.execsql ("CREATE TABLE Demo" (_id INTEGER PRIMARY KEY, name TEXT);
}
@Override
public void Onupgrade (sqlitedatabase db, int old, int newver) {
}
}
}
This example does not use ContentProvider but lets the activity directly manipulate the sqlitedatabase to implement the data management, or use the file directly to manage the data without the database.
This approach may be simpler to implement in a way that requires little or no data and is used only by a single component. But it's also obvious that passing between components can be cumbersome and not even shared between components. In order to share, it is necessary to abstract the data layer so that it is independent of any activity to meet different components of the data read and write, but this is not the same as the implementation of a contentprovider, it is better to achieve a contentprovider convenience.
So, the rule is that if some data is used only in one activity, then there is no need to create contentprovider, use files directly or manipulate the database directly to achieve the goal. But if you need to share and pass data to other components, you must use ContentProvider.
In addition, with the contentprovider can also facilitate interaction with other applications, data transfer to other applications of the components.
In the use of sqliteopenhelper must pay attention to thread synchronization issues, to ensure that each sqlitedatabase method (such as execsql) thread security, otherwise it may cause very rare exceptions. You have encountered a sqlitestatement NPE (nullpointerexception) because there are multiple threads operating the same sqliteopenhelper, and there is no synchronization.