Android數(shù)據(jù)持久化之ContentProvider機(jī)制詳解
本文實(shí)例講述了Android數(shù)據(jù)持久化之ContentProvider機(jī)制。分享給大家供大家參考,具體如下:
一般而言,android操作系統(tǒng)的應(yīng)用程序所建立的數(shù)據(jù)只允許自己使用,應(yīng)用程序彼此間無(wú)法借助公用存儲(chǔ)器來(lái)共享數(shù)據(jù),android系統(tǒng)提供了一個(gè)機(jī)制,即內(nèi)容提供器(ContentProvider),來(lái)公開自己私有的數(shù)據(jù)到數(shù)據(jù)內(nèi)容器,通過該機(jī)制,可以供其他應(yīng)用程序來(lái)讀取自己內(nèi)部的數(shù)據(jù),當(dāng)然也可以訪問其他應(yīng)用程序的數(shù)據(jù)。通常,內(nèi)容提供器背后都有SQLite數(shù)據(jù)庫(kù)的支持,用以存儲(chǔ)內(nèi)容提供內(nèi)部數(shù)據(jù)。
實(shí)現(xiàn)ContentProvider與實(shí)現(xiàn)SQLite的區(qū)別:
應(yīng)用程序?qū)崿F(xiàn)SQLite時(shí),由應(yīng)用程序直接與數(shù)據(jù)庫(kù)進(jìn)行對(duì)接,所以要在應(yīng)用程序中實(shí)現(xiàn)SQLite的接口:db.onCreate()、db.insert()、db.update()、db.delete()、db.query()和db.close();
實(shí)現(xiàn)內(nèi)容提供器時(shí),在應(yīng)用程序與數(shù)據(jù)庫(kù)之間要實(shí)現(xiàn)一個(gè)ContentProvider程序,這個(gè)ContentProvider程序會(huì)直接與數(shù)據(jù)庫(kù)進(jìn)行對(duì)接,此時(shí)應(yīng)用程序需要實(shí)現(xiàn)和ContentProvider程序接口的方法。
下面該說(shuō)說(shuō)如何建立內(nèi)容提供器了:
首先,實(shí)現(xiàn)內(nèi)容提供器接口:
實(shí)現(xiàn)該接口的5個(gè)重要方法;
其次,定義數(shù)據(jù)Uri:
提供器應(yīng)用程序需要定義一個(gè)“基底”Uri,以供其他應(yīng)用程序訪問這一內(nèi)容提供器,這一個(gè)Uri必須是唯一的,且必須是以“content://”開頭,content: 表示內(nèi)容提供器程序所控制數(shù)據(jù)的位置;在AndroidManifest.xml配置文件中添加如下代碼以進(jìn)行聲明:
<!-- 設(shè)置類名和授權(quán) multiprocess屬性是數(shù)據(jù)的同步性(同一時(shí)間可能有多個(gè)程序訪問該內(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();
定義一個(gè)Uri所在的位置,并設(shè)置一個(gè)變量來(lái)找到內(nèi)容提供器程序的接口;
如下是一個(gè)完整的代碼,功能是實(shí)現(xiàn)內(nèi)容提供器的建立以及通過該內(nèi)容提供器程序來(lái)添加和檢索數(shù)據(jù):
實(shí)現(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
// 實(shí)現(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ù)的同步性(同一時(shí)間可能有多個(gè)程序訪問該內(nèi)容提供器)--> <provider android:name="ContentProviderClass" android:multiprocess="true" android:authorities="com.example.data_contentprovider.ContentProviderClass" > </provider>
建立一個(gè)SQLite數(shù)據(jù)庫(kù)系統(tǒng)來(lái)存儲(chǔ)和管理數(shù)據(jù),同時(shí)利用SQLiteOpenHilper類協(xié)助建立數(shù)據(jù)庫(kù)和SQLiteDatabase類來(lái)管理數(shù)據(jù)庫(kù):
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ù)庫(kù)
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對(duì)象(在應(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ù)庫(kù)并向其添加數(shù)據(jù)了。
ContentProvider中重要的幾個(gè)類:
UriMatcher:
要了解UriMatcher,首先需要了解android中的Uri表示方法,眾所周知,Uri為通用資源標(biāo)識(shí)符,它代表的是要操作的數(shù)據(jù),Android中的每一種資源(比如文本,圖像,視頻等)都可以用Uri來(lái)表示。Android中的Uri由以下三部分組成:”content://”(即authory),數(shù)據(jù)的路徑,資源標(biāo)識(shí)ID(可選),其中如果存在ID,則表示某一個(gè)具體的資源,如果不存在ID,則表示路徑下的整體。因此addUri()函數(shù)的3個(gè)參數(shù)也是對(duì)應(yīng)上面的那3個(gè)。UriMatcher的匹配過程分為3步:初始化UriMatcher;注冊(cè)需要用的Uri;與已經(jīng)注冊(cè)的Uri進(jìn)行匹配。
ContentResolver :
當(dāng)使用ContentProvider在不同的應(yīng)用程序共享數(shù)據(jù)時(shí),其數(shù)據(jù)的暴露方式是采取類似數(shù)據(jù)庫(kù)中表的方法。而ContentResolver 是恰好是采用類似數(shù)據(jù)庫(kù)的方法來(lái)從ContentProvider中存取數(shù)據(jù)的,它是通過Uri來(lái)查詢ContentProvider中提供的數(shù)據(jù),查詢時(shí),還需知道目的數(shù)據(jù)庫(kù)的名稱,數(shù)據(jù)段的數(shù)據(jù)類型,或者說(shuō)資源的ID。
SQLiteQueryBuilder:
是一個(gè)用來(lái)生產(chǎn)SQL查詢語(yǔ)句的輔助類,可以方便的去訪問SQLiteDatabase. 在構(gòu)造SQL查詢語(yǔ)句時(shí),它同樣也需要指定表名,指定列名,指定where條件等。
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
相關(guān)文章
Android實(shí)現(xiàn)單頁(yè)面浮層可拖動(dòng)view的示例代碼
本篇文章主要介紹了Android實(shí)現(xiàn)單頁(yè)面浮層可拖動(dòng)view的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Flutter+Metal實(shí)現(xiàn)圖像處理詳細(xì)流程
Flutter使用CVPixelBuffer和iOS交互,我們可以直接使用CVPixelBuffer創(chuàng)建MTLTexture,然后將MTLTexture設(shè)置為渲染目標(biāo),這篇文章主要介紹了Flutter+Metal實(shí)現(xiàn)圖像處理,需要的朋友可以參考下2022-06-06
Android將項(xiàng)目導(dǎo)出為L(zhǎng)ibrary并在項(xiàng)目中使用教程
這篇文章主要介紹了Android將項(xiàng)目導(dǎo)出為L(zhǎng)ibrary并在項(xiàng)目中使用教程,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07
Flutter StaggeredGridView實(shí)現(xiàn)瀑布流效果
這篇文章主要為大家詳細(xì)介紹了Flutter StaggeredGridView實(shí)現(xiàn)瀑布流效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Android自定義view 你所需要知道的基本函數(shù)總結(jié)
這篇文章主要介紹了Android自定義view 你所需要知道的基本函數(shù)的相關(guān)資料,需要的朋友可以參考下2017-02-02
Android中EditText光標(biāo)的顯示與隱藏方法
這篇文章主要給大家介紹了關(guān)于Android中EditText光標(biāo)的顯示與隱藏以及Android之第一次不顯示EditText光標(biāo)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-11-11
Android TabLayout(選項(xiàng)卡布局)簡(jiǎn)單用法實(shí)例分析
這篇文章主要介紹了Android TabLayout(選項(xiàng)卡布局)簡(jiǎn)單用法,結(jié)合實(shí)例形式簡(jiǎn)單分析了Android選項(xiàng)卡布局的界面布局與功能實(shí)現(xiàn)具體相關(guān)技巧,需要的朋友可以參考下2016-01-01
Handler實(shí)現(xiàn)倒計(jì)時(shí)功能
這篇文章主要為大家詳細(xì)介紹了Handler實(shí)現(xiàn)倒計(jì)時(shí)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04

