Android數(shù)據(jù)持久化之ContentProvider機(jī)制詳解
本文實例講述了Android數(shù)據(jù)持久化之ContentProvider機(jī)制。分享給大家供大家參考,具體如下:
一般而言,android操作系統(tǒng)的應(yīng)用程序所建立的數(shù)據(jù)只允許自己使用,應(yīng)用程序彼此間無法借助公用存儲器來共享數(shù)據(jù),android系統(tǒng)提供了一個機(jī)制,即內(nèi)容提供器(ContentProvider),來公開自己私有的數(shù)據(jù)到數(shù)據(jù)內(nèi)容器,通過該機(jī)制,可以供其他應(yīng)用程序來讀取自己內(nèi)部的數(shù)據(jù),當(dāng)然也可以訪問其他應(yīng)用程序的數(shù)據(jù)。通常,內(nèi)容提供器背后都有SQLite數(shù)據(jù)庫的支持,用以存儲內(nèi)容提供內(nèi)部數(shù)據(jù)。
實現(xiàn)ContentProvider與實現(xiàn)SQLite的區(qū)別:
應(yīng)用程序?qū)崿F(xiàn)SQLite時,由應(yīng)用程序直接與數(shù)據(jù)庫進(jìn)行對接,所以要在應(yīng)用程序中實現(xiàn)SQLite的接口:db.onCreate()、db.insert()、db.update()、db.delete()、db.query()和db.close();
實現(xiàn)內(nèi)容提供器時,在應(yīng)用程序與數(shù)據(jù)庫之間要實現(xiàn)一個ContentProvider程序,這個ContentProvider程序會直接與數(shù)據(jù)庫進(jìn)行對接,此時應(yīng)用程序需要實現(xiàn)和ContentProvider程序接口的方法。
下面該說說如何建立內(nèi)容提供器了:
首先,實現(xiàn)內(nèi)容提供器接口:
實現(xiàn)該接口的5個重要方法;
其次,定義數(shù)據(jù)Uri:
提供器應(yīng)用程序需要定義一個“基底”Uri,以供其他應(yīng)用程序訪問這一內(nèi)容提供器,這一個Uri必須是唯一的,且必須是以“content://”開頭,content: 表示內(nèi)容提供器程序所控制數(shù)據(jù)的位置;在AndroidManifest.xml配置文件中添加如下代碼以進(jìn)行聲明:
<!-- 設(shè)置類名和授權(quán) multiprocess屬性是數(shù)據(jù)的同步性(同一時間可能有多個程序訪問該內(nèi)容提供器)--> <provider android:name="ContentProviderClass" android:multiprocess="true" android:authorities="com.example.data_contentprovider.ContentProviderClass" > </provider>
在應(yīng)用程序中添加如下代碼:
//acquire the Uri of ContentProvider
getIntent().setData(Uri.parse("content://com.example.data_contentprovider.ContentProviderClass"));
Uri uri = getIntent().getData();
定義一個Uri所在的位置,并設(shè)置一個變量來找到內(nèi)容提供器程序的接口;
如下是一個完整的代碼,功能是實現(xiàn)內(nèi)容提供器的建立以及通過該內(nèi)容提供器程序來添加和檢索數(shù)據(jù):
實現(xiàn)內(nèi)容提供器接口的代碼:
package com.example.data_contentprovider;
import com.example.data_contentprovider.DB.DBHelper;
import android.net.Uri;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
public class ContentProviderClass extends ContentProvider {
DBHelper dataBaseHelper; // 定義DataBaseHelper類變量dataBaseHelper
// 實現(xiàn)ContentProvider的onCreate方法
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
dataBaseHelper = new DBHelper(getContext());
return true;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
SQLiteDatabase db = dataBaseHelper.getWritableDatabase();
db.insert("test", null, values);
return null;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
SQLiteDatabase db = dataBaseHelper.getReadableDatabase();
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables("test");
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, null);
return cursor;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
配置AndroidManifest.xml文件:
<!-- 設(shè)置類名和授權(quán) multiprocess屬性是數(shù)據(jù)的同步性(同一時間可能有多個程序訪問該內(nèi)容提供器)--> <provider android:name="ContentProviderClass" android:multiprocess="true" android:authorities="com.example.data_contentprovider.ContentProviderClass" > </provider>
建立一個SQLite數(shù)據(jù)庫系統(tǒng)來存儲和管理數(shù)據(jù),同時利用SQLiteOpenHilper類協(xié)助建立數(shù)據(jù)庫和SQLiteDatabase類來管理數(shù)據(jù)庫:
package com.example.data_contentprovider.DB;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
public class DBHelper extends SQLiteOpenHelper {
// 建立test.db數(shù)據(jù)庫
public DBHelper(Context context) {
super(context, "test.db", null, 1);
}
// 建立test表
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table test (" + BaseColumns._ID
+ "integer primary key," + "name text," + "description text"
+ ");");
}
// 更新新版本
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS test");
onCreate(db);
}
}
下面就是provider的應(yīng)用程序了:
package com.example.data_contentprovider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
public class ContentProviderActivity extends Activity {
String [] from = {"column00","column01","column02"};
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//acquire the Uri of ContentProvider
getIntent().setData(Uri.parse("content://com.example.data_contentprovider.ContentProviderClass"));
Uri uri = getIntent().getData();
//create some data to test
ContentValues values = new ContentValues();
values.put("name", "marry");
values.put("description", "123456");
getContentResolver().insert(uri, values); //獲取ContentResolver對象(在應(yīng)用程序B中,通過ContentResolver獲取程序A的ContentProvider中的數(shù)據(jù)。)
values.put("name", "hello");
values.put("description", "654321");
getContentResolver().insert(uri, values);
//search db all colum,cursor point to first colum of result
Cursor cursor = managedQuery(uri, null, null, null, null);
cursor.moveToFirst();
//set ArrayList,view more field table
ArrayList<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
Map<String, Object> item;
//from db read data and save to ArrayList data container
for (int i = 0; i < cursor.getCount(); i++) {
item = new HashMap<String, Object>();
item.put("column00", cursor.getString(0));
item.put("column01", cursor.getString(1));
item.put("column02", cursor.getString(2));
data.add(item);
cursor.moveToNext();
}
cursor.close();
//ArrayList container data save to listView
ListView listView = new ListView(this);
SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.activity_content_provider, from, new int[]{R.id.text1,R.id.text2,R.id.text3});
listView.setAdapter(adapter);
setContentView(listView);
}
}
provider應(yīng)用程序就可以通過該內(nèi)容提供器檢索數(shù)據(jù)庫并向其添加數(shù)據(jù)了。
ContentProvider中重要的幾個類:
UriMatcher:
要了解UriMatcher,首先需要了解android中的Uri表示方法,眾所周知,Uri為通用資源標(biāo)識符,它代表的是要操作的數(shù)據(jù),Android中的每一種資源(比如文本,圖像,視頻等)都可以用Uri來表示。Android中的Uri由以下三部分組成:”content://”(即authory),數(shù)據(jù)的路徑,資源標(biāo)識ID(可選),其中如果存在ID,則表示某一個具體的資源,如果不存在ID,則表示路徑下的整體。因此addUri()函數(shù)的3個參數(shù)也是對應(yīng)上面的那3個。UriMatcher的匹配過程分為3步:初始化UriMatcher;注冊需要用的Uri;與已經(jīng)注冊的Uri進(jìn)行匹配。
ContentResolver :
當(dāng)使用ContentProvider在不同的應(yīng)用程序共享數(shù)據(jù)時,其數(shù)據(jù)的暴露方式是采取類似數(shù)據(jù)庫中表的方法。而ContentResolver 是恰好是采用類似數(shù)據(jù)庫的方法來從ContentProvider中存取數(shù)據(jù)的,它是通過Uri來查詢ContentProvider中提供的數(shù)據(jù),查詢時,還需知道目的數(shù)據(jù)庫的名稱,數(shù)據(jù)段的數(shù)據(jù)類型,或者說資源的ID。
SQLiteQueryBuilder:
是一個用來生產(chǎn)SQL查詢語句的輔助類,可以方便的去訪問SQLiteDatabase. 在構(gòu)造SQL查詢語句時,它同樣也需要指定表名,指定列名,指定where條件等。
希望本文所述對大家Android程序設(shè)計有所幫助。
相關(guān)文章
Android頂部狀態(tài)欄透明化并釋放空間的兩種實現(xiàn)方法
這篇文章主要介紹了Android頂部狀態(tài)欄透明化并釋放空間的兩種實現(xiàn)方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-03-03
Android NestedScrolling嵌套滾動的示例代碼
這篇文章主要介紹了Android NestedScrolling嵌套滾動的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
android使用handlerthread創(chuàng)建線程示例
這篇文章主要介紹了android使用handlerthread創(chuàng)建線程,講解了這種方式的好處及為什么不使用Thread類的原因2014-01-01
Android ScrollView嵌套ExpandableListView顯示不正常的問題的解決辦法
這篇文章主要介紹了Android ScrollView嵌套ExpandableListView顯示不正常的問題的解決辦法的相關(guān)資料,需要的朋友可以參考下2017-02-02
android播放視頻時在立體聲與單聲道之間切換無變化原因分析及解決
使用第三方視頻播放器,有立體聲與單聲道之間切換,發(fā)現(xiàn)切換后無作用,原因是由于在HAL層默認(rèn)沒有處理上層發(fā)的stereo 轉(zhuǎn)mono的命令,具體的解決方法如下2013-06-06
詳談自定義View之GridView單選 金額選擇Layout-ChooseMoneyLayout
下面小編就為大家?guī)硪黄斦勛远xView之GridView單選 金額選擇Layout-ChooseMoneyLayout。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
android4.0混淆XmlPullParser報錯原因分析解決
今天,用android4.0在proguard-project.txt中加入 -libraryjars libs/ksoap2-android-assembly-2.6.0-jar-with-dependencies.jar這句話后,混淆時報上面的錯誤,下面與大家分享下具體的解決方法2013-06-06

