ContentProvider 使用示例

contentProvider是Android中提供的專門用于不同應(yīng)用間進(jìn)行數(shù)據(jù)共享方式,作為四大組件之一的contentProvider,使用起來(lái)比較簡(jiǎn)單,但是因?yàn)槭褂妙l率不是很高,所以經(jīng)常遺忘其使用方法,所以在次記錄下其基本用法的實(shí)例。


首先,有必要對(duì)contentProvider的基本原理進(jìn)行一個(gè)簡(jiǎn)單的討論。
contentProvider的底層實(shí)現(xiàn)是通過(guò)Binder實(shí)現(xiàn),但是他的使用比aidl要簡(jiǎn)單很多,因?yàn)橄到y(tǒng)已經(jīng)為我們做了很多的封裝。
系統(tǒng)中也為我們提供了非常多的ContentProvider,比如通訊錄,日程表,通話記錄等,要跨進(jìn)程訪問(wèn)這些信息,只需要通過(guò)ContentResolver的query、update、insert、update、insert、delete方法即可。
要實(shí)現(xiàn)自定義ContentProvider,繼承ContentProvider類并實(shí)現(xiàn)六個(gè)抽象方法即可,這六個(gè)抽象方法分別是是:OnCreate、query、update、insert、delete和getType。需要注意的是在這六個(gè)方法中,除了OnCreate由系統(tǒng)回調(diào)并運(yùn)行在主線程里,其他五個(gè)方法均由外界回調(diào)并運(yùn)行在Binder線程池中。

下面我們自定義一個(gè)BookProvider繼承自ContentProvider,其代碼如下:

public class BookProvider extends ContentProvider {

public static final String TAG = "reoger.hut.hello.word";

public static final String AUTHORLTY = "reoger.hut.hello.word";

public static final Uri BOOK_CONTENT_URI = Uri.parse("content://"+AUTHORLTY+"/book");
public static final Uri USER_CONTENT_URI = Uri.parse("content://"+AUTHORLTY+"/user");

public static final int BOOK_URI_CODE = 0;
public static final int USER_URI_CODE = 1;

private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

private Context mContext;
private SQLiteDatabase mDb;

static {
sUriMatcher.addURI(AUTHORLTY,"book",BOOK_URI_CODE);
sUriMatcher.addURI(AUTHORLTY,"user",USER_URI_CODE);
}

private String getTableName(Uri uri){
String tableName = null;
switch (sUriMatcher.match(uri)){
case BOOK_URI_CODE:
tableName = DbOpenHelper.BOOK_TABLE_NAME;
break;
case USER_URI_CODE:
tableName = DbOpenHelper.USER_TABLE_NAME;
break;
default:
break;
}
return tableName;
}

@Override
public boolean onCreate() {
Log.d(TAG, "onCreate: " + Thread.currentThread());
mContext = getContext();
initProvider();
return true;
}

/**
* 初始化數(shù)據(jù)庫(kù)
*/
private void initProvider() {
mDb = new DbOpenHelper(mContext).getWritableDatabase();
mDb.execSQL("delete from "+DbOpenHelper.BOOK_TABLE_NAME);
mDb.execSQL("delete from "+DbOpenHelper.USER_TABLE_NAME);
mDb.execSQL("insert into book values(3,'android');");
mDb.execSQL("insert into book values(4,'ios');");
mDb.execSQL("insert into book values(5,'html5');");
mDb.execSQL("insert into user values(1,'jack',1);");
mDb.execSQL("insert into user values(2,'jany',0);");

}

@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
Log.d(TAG, "query: " + Thread.currentThread().getName());

String table = getTableName(uri);
if(table == null){
throw new IllegalArgumentException(" UnSupported URL: "+uri);
}
return mDb.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
}

@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}

@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
Log.d(TAG, "insert: ");

String table = getTableName(uri);
if(table == null ){
throw new IllegalArgumentException("UnSupported URI :"+uri);
}
mDb.insert(table,null,values);
mContext.getContentResolver().notifyChange(uri,null);
return uri;
}

@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
Log.d(TAG, "delete: ");
String table = getTableName(uri);
if(table == null ){
throw new IllegalArgumentException("UnSupported URI :"+uri);
}
int count = mDb.delete(table,selection,selectionArgs);
if(count>0){
getContext().getContentResolver().notifyChange(uri,null);
}
return count;
}

@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
Log.d(TAG, "update: ");
String table = getTableName(uri);
if(table == null ){
throw new IllegalArgumentException("UnSupported URI :"+uri);
}
int row = mDb.update(table,values,selection,selectionArgs);
if(row >0 ){
getContext().getContentResolver().notifyChange(uri,null);
}
return row;
}
}

因?yàn)槠涔蚕淼膬?nèi)容通過(guò)數(shù)據(jù)庫(kù)存儲(chǔ),所以需要一個(gè)數(shù)據(jù)庫(kù)的幫助類。用來(lái)幫我們創(chuàng)建數(shù)據(jù)庫(kù),代碼很簡(jiǎn)單,DbOpenHelper的代碼如下:

public class DbOpenHelper extends SQLiteOpenHelper {

private static final String DB_NAME = "boook_provider.db";
public static final String BOOK_TABLE_NAME = "book";
public static final String USER_TABLE_NAME = "user";

private static final int DB_VERSION = 1;

private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS "
+ BOOK_TABLE_NAME + "( _id INTEGER PRIMARY KEY," + "name TEXT)";
private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS "
+ USER_TABLE_NAME + "( _id INTEGER PRIMARY KEY," + "name TEXT ,"+"sex INT)";

public DbOpenHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK_TABLE);
db.execSQL(CREATE_USER_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}

需要說(shuō)明的是,CongetProvider可以共享的數(shù)據(jù)不僅只是數(shù)據(jù)庫(kù)的,也可以共享文件中的數(shù)據(jù),甚至可以共享內(nèi)存中的數(shù)據(jù)。這里只是通過(guò)共享數(shù)據(jù)庫(kù)中的內(nèi)容作為示例 。
當(dāng)然,作為android四大組件,都是需要在manifest中進(jìn)行申明(當(dāng)然,broadcast也可以在java代碼中進(jìn)行聲明)。所以這里BookProvider聲明的代碼如下:

<provider
android:name=".BookProvider"
android:authorities="reoger.hut.hello.word"
android:permission="com.reoger.hello"
android:process=":provider"
/>

其中authorities屬性就聲明了外界訪問(wèn)這個(gè)ContentProvider的Uri。例如此處訪問(wèn)的URI的值應(yīng)該是:content://reoger.hut.hello.word 。
通過(guò)permission屬性為provider定制權(quán)限,需要訪問(wèn)此provider必須聲明此處定義的permission,否則無(wú)法正常獲取到信息。當(dāng)然,為了讓其運(yùn)行在一個(gè)單獨(dú)的進(jìn)程中,指定了process屬性。

通過(guò)前面的代碼,自定義的ContentProvider已經(jīng)實(shí)現(xiàn)完畢,接下來(lái)我們來(lái)檢驗(yàn)自定義的BookProvider是否正常工作。
MainActivity代碼如下;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Uri uri = Uri.parse("content://reoger.hut.hello.word/book");

ContentValues values = new ContentValues();
values.put("_id",6);
values.put("name","Android 開發(fā)藝術(shù)");
getContentResolver().insert(uri,values);

Cursor bookCursor = getContentResolver().query(uri,new String[]{"_id","name"},null,null,null);
while(bookCursor.moveToNext()){
Book book = new Book(bookCursor.getInt(0),bookCursor.getString(1));
Log.d("TAG","bookID "+book.toString());
}
bookCursor.close();

Uri uri2 = Uri.parse("content://reoger.hut.hello.word/user");

ContentValues values2 = new ContentValues();
values2.put("_id",3);
values2.put("name","reoger");
values.put("sex","0");
getContentResolver().insert(uri2,values2);

Cursor bookCursor2 = getContentResolver().query(uri2,new String[]{"_id","name","sex"},null,null,null);
while(bookCursor2.moveToNext()){
User user = new User(bookCursor2.getInt(0),bookCursor2.getString(1),bookCursor2.getInt(2));
Log.d("TAG","bookID "+user.toString());
}
bookCursor2.close();
}
}

通過(guò)打印的日志信息,發(fā)現(xiàn)我們的測(cè)試示例完全符合我們的期望。結(jié)果如圖所示:

15-50-29.jpg

最后,補(bǔ)充一下其中Book和User的代碼:

public class Book implements Parcelable{
public Book(int id, String name) {
this.id = id;
this.name = name;
}

private int id;
private String name;

public Book() {
}

protected Book(Parcel in) {
id = in.readInt();
name = in.readString();
}

public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}

@Override
public Book[] newArray(int size) {
return new Book[size];
}
};

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
}

@Override
public String toString() {
String result = "book = ["+id+
","+name+"];";
return result;
}
}

public class User implements Parcelable {

private int id;
private String name;
private int sex;

public User(int id, String name, int sex) {
this.id = id;
this.name = name;
this.sex = sex;
}

@Override
public String toString() {
return "id= "+id+" ,name ="+name+" ,sex= "+sex;
}

protected User(Parcel in) {
id = in.readInt();
name = in.readString();
sex = in.readInt();
}

public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}

@Override
public User[] newArray(int size) {
return new User[size];
}
};

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
dest.writeInt(sex);
}
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容