ContentProvider作為Android的四大儲存方式之一,有著廣泛的應用性,它暴露了資料地址,可以讓其他應用訪問資料,可以用於儲存圖片、通訊錄等資訊,這篇博文將詳細介紹ContentProvider、URIMatcher,LoaderManager,cursorAdapter的方法使用與介紹。使用ContentProvider的時候一定要注意在manifest資訊清單檔中像Acticity檔案一樣,聲明其屬性。
此外因為我們是用loadermanager來載入資料,MainAcitivity類要實現LoaderCallback介面。按照慣例我們還是看下Google官方文檔對contentprovider的解釋,ContentProvider管理一個結構化的資料集。它封裝了資料,並提供定義資料安全機制。ContentProvider的標準介面實現多線程機制來串連資料,一般是用loaderManager非同步載入資料。當你想要訪問資料在一個ContentProvider,我們使用ContentResolver對象在應用程式的上下文中作為溝通方法。ContentResolver用來解析請求碼返還資料。
我們先看看一下本次介紹的工程的目錄結構
MainActivity的代碼
package com.example.f14_contentprovider;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import android.net.Uri;import android.os.Bundle;import android.app.Activity;import android.app.LoaderManager;import android.app.LoaderManager.LoaderCallbacks;import android.content.ContentResolver;import android.content.ContentValues;import android.content.CursorLoader;import android.content.Loader;import android.database.Cursor;import android.view.Menu;import android.view.View;import android.widget.Button;import android.widget.ListView;import android.widget.SimpleCursorAdapter;public class MainActivity extends Activity implements LoaderCallbacks<Cursor> {private Button button;private ListView listView;private LoaderManager loaderManager;private SimpleCursorAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) this.findViewById(R.id.button1);listView = (ListView) this.findViewById(R.id.listView1);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubContentResolver resolver = getContentResolver();Uri uri = Uri.parse("content://com.example.f14_contentprovider.PersonContentProvider/person");ContentValues values = new ContentValues();values.put("name", "jack");values.put("address", "hangzhou");resolver.insert(uri, values);loaderManager.restartLoader(1001, null, MainActivity.this);}});loaderManager = getLoaderManager();loaderManager.initLoader(1001, null, this);}@Overridepublic Loader<Cursor> onCreateLoader(int id, Bundle args) {// TODO Auto-generated method stub/** * CursorLoader該類用於載入程式,查詢ContentResolver並返回一個指標。這個類實現了裝載機協議查詢遊標的標準方法, * 基於AsyncTaskLoader執行遊標查詢在一個後台線程,以便它不會阻止應用程式的UI。 */CursorLoader loader = new CursorLoader(this);Uri uri = Uri.parse("content://com.example.f14_contentprovider.PersonContentProvider/person");loader.setUri(uri);loader.setProjection(new String[] { "name", "address" });return loader;}@SuppressWarnings("deprecation")@Overridepublic void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {// TODO Auto-generated method stubList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();// 載入資料while (arg1.moveToNext()) {HashMap<String, String> map = new HashMap<String, String>();map.put("name", arg1.getString(arg1.getColumnIndex("name")));map.put("address", arg1.getString(arg1.getColumnIndex("address")));list.add(map);}adapter = new SimpleCursorAdapter(this, R.layout.item, arg1,new String[] { "name", "address" }, new int[] { R.id.textView1,R.id.textView2 });listView.setAdapter(adapter);adapter.notifyDataSetChanged();// 若內容發生變化 觸發該方法}@Overridepublic void onLoaderReset(Loader<Cursor> arg0) {// TODO Auto-generated method stub}} 如上所示,在MainAcitivity主方法中,大家可以看到第40-47行代碼中,通過內容提供者contentProvider插入資料的時候,是通過contentResolver進行串連,通過其insert方法提供插入指定的資料表和資料完成操作。操作完成後還需要調用loadermanager的restart方法更新一次UI。
PersonContentProvider繼承了ContentProvider的方法
package com.example.f14_contentprovider;import android.content.ContentProvider;import android.content.ContentResolver;import android.content.ContentUris;import android.content.ContentValues;import android.content.UriMatcher;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.net.Uri;//要在manifest檔案中註冊providerpublic class PersonContentProvider extends ContentProvider {private MyOpenHelper helper;private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);// 專門用來匹配URI的類private static final int PERSONS = 1;private static final int PERSON = 2;private ContentResolver resolver;static {matcher.addURI("com.example.f14_contentprovider.PersonContentProvider","person", PERSONS);matcher.addURI("com.example.f14_contentprovider.PersonContentProvider","person/#", PERSON);}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {// TODO Auto-generated method stubreturn 0;}// 當您需要匹配一個URI,調用匹配(URI),用來來建立一個查詢,傳回型別,插入或刪除一行。@Overridepublic String getType(Uri arg0) {// TODO Auto-generated method stubint match = matcher.match(arg0);switch (match) {case PERSONS:return "vnd.android.cursor.dir/person";case PERSON:return "vnd.android.cursor.item/person";default:return null;}}@Overridepublic Uri insert(Uri uri, ContentValues values) {// TODO Auto-generated method stubSQLiteDatabase database = helper.getWritableDatabase();long id = database.insert("person", null, values);Uri rUri = ContentUris.withAppendedId(uri, id);resolver.notifyChange(rUri, null);return rUri;}@Overridepublic boolean onCreate() {// TODO Auto-generated method stubhelper = new MyOpenHelper(getContext());resolver = getContext().getContentResolver();return true;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {// TODO Auto-generated method stubCursor cursor = null;int flag = matcher.match(uri);SQLiteDatabase database = helper.getReadableDatabase();switch (flag) {case PERSONS: cursor=database.query("person", null, null, null,null, null, null);break;case PERSON:long _id = ContentUris.parseId(uri);String where_value = " _id = " + _id;if (selection != null && !selection.equals("")) {where_value += selection;}cursor = database.query("person", projection, where_value,selectionArgs, null, null, sortOrder);break;default:break;}cursor.setNotificationUri(resolver, uri);return cursor;}@Overridepublic int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {// TODO Auto-generated method stubreturn 0;}}
資料庫建立類MyopenHelper
package com.example.f14_contentprovider;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;public class MyOpenHelper extends SQLiteOpenHelper {private static final int DATABASE_VERSION = 1;private static final String PERSON_TABLE_NAME = "person";public MyOpenHelper(Context context) {super(context, PERSON_TABLE_NAME, null, DATABASE_VERSION);// TODO Auto-generated constructor stub}@Overridepublic void onCreate(SQLiteDatabase db) {// TODO Auto-generated method stubdb.execSQL("create table "+ PERSON_TABLE_NAME+ "(_id integer primary key autoincrement,name varchar(64),address varchar(64))");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// TODO Auto-generated method stub}}