作爲ANDROIDL四大組件(Compenent:Activity, Service, BreadcaseReceiver,ContentProvider)之一的Content provider,爲其它應用程序(也可以是提供該Content provider的應用程序)提供了一個接口一致數據儲存模型。通過該接口,你可以方便地提取你想要的數據,修改或者是刪除都會變得相當方便。依照 ANDROI組件模型的原理,把數據儲存與數據顯示分離天來,這不但提高了組件重用性,也同時提供更高的完全性(每一個Content Provider都有自己的許可屬性)。作爲數據儲存的後端,你可以使用有Sqlite3保存數據,也可以使用文件系統保存,甚至是使用網絡;後端的多樣 性給得程序的設計更富有彈性。
今天結合自己開發的經驗,總結一下實現Content Provider的幾點經驗,不足之處,歡迎討論
通過擴展 ContentProvider 類來創建一個新的 Content Provider 。重寫 onCreate 方法來打開或初始化你要通過這個 Provider 提供的底層數據源。新的 Content Provider 的框架代碼如下所示:
import android.content.*;
import android.database.Cursor;
import android.net.Uri;
import android.database.SQLException;
public class MyProvider extends ContentProvider
{
@Override
public boolean onCreate()
{
// TODO: Construct the underlying database.
return true;
}
}
你還應該暴露一個公共的靜態變量 CONTENT_URI ,來返回這個 Provider 的 URI 。
Content URI 在 Provider 間必須是獨一無二的,所以,一個好的習慣是: URI 路徑值使用包名。定義一個 Content Provider URI 的通用格式是:
content://com.<CompanyName>.provider.<ApplicationName>/<DataPath>
例如:
content://com.paad.provider.myapp/items
Content URI 可以表示爲兩種形式。上面的 URI 表示請求某類型的全部值(例如,所有項目)。
在其後追加 /<rownumber> ,如下所示,表示請求單一記錄(例如,第 5 個項目)。
content://com.paad.provider.myapp/items/5
支持這兩種方式來訪問你的 Provider 是個很好的形式。
做到這樣最簡單的方式是使用一個 UriMatcher 。當通過 ContentResolver 來訪問一個 Provider 時,配置 UriMatcher 解析 URI 來決定它們的形式。下面的代碼顯示了這一樣式的框架代碼:
public class MyProvider extends ContentProvider
{
private static final String myURI =“content://com.paad.provider.myapp/items”;
public static final Uri CONTENT_URI = Uri.parse(myURI);
@Override
public boolean onCreate()
{
// TODO: Construct the underlying database.
return true;
}
// Create the constants used to differentiate between the different
// URI requests.
private static final int ALLROWS = 1;
private static final int SINGLE_ROW = 2;
private static final UriMatcher uriMatcher;
// Populate the UriMatcher object, where a URI ending in ‘items’ will
// correspond to a request for all items, and ‘items/[rowID]’
// represents a single row.
static
{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(“com.paad.provider.myApp”, “items”, ALLROWS);
uriMatcher.addURI(“com.paad.provider.myApp”, “items/#”,SINGLE_ROW);
}
}
你可以使用相同的技巧來暴露數據中不同子集的 URI 或數據庫中不同的表的 URI 。
一個好的習慣是:在 Provider 中保留列的名稱和索引,來簡化通過 Cursor 提取信息。
暴露數據源的訪問
你可以實現 delete 、 insert 、 update 和 query 方法來暴露與你的 Content Provider 的查詢和交互功能。
這些方法作爲底層數據源的通用接口,允許 Android 應用程序跨越程序邊界來共享數據,而不需要爲每個程序公佈不同的接口。
最常見的場景是使用一個 Content Provider 來訪問一個私有的 SQLite 數據庫,但使用這些方法,你可以訪問任何數據源(包括文件或應用程序實例的變量)。
接下來的框架代碼顯示了一個 Content Provider 的查詢和交互功能。注意: UriMatcher 對象用於精煉交互和查詢請求。
@Override
public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sort)
{
// If this is a row query, limit the result set to the passed in row.
switch (uriMatcher.match(uri))
{
case SINGLE_ROW :
// TODO: Modify selection based on row id, where:
// rowNumber = uri.getPathSegments().get(1));
}
return null;
}
@Override
public Uri insert(Uri _uri, ContentValues _initialValues) {
long rowID = [ ... Add a new item ... ]
// Return a URI to the newly added item.
if (rowID > 0)
{
return ContentUris.withAppendedId(CONTENT_URI, rowID);
}
throw new SQLException(“Failed to add new item into “ + _uri);
}
@Override
public int delete(Uri uri, String where, String[] whereArgs)
{
switch (uriMatcher.match(uri))
{
case ALLROWS:
case SINGLE_ROW:
default: throw new IllegalArgumentException(“Unsupported URI:” + uri);
}
}
@Override
public int update(Uri uri, ContentValues values, String where,String[] whereArgs)
{
switch (uriMatcher.match(uri))
{
case ALLROWS:
case SINGLE_ROW:
default: throw new IllegalArgumentException(“Unsupported URI:” + uri);
}
}
創建 Content Provider 最後一步是定義標識 Provider 返回數據的 MIME 類型。
重寫 getType 方法,返回一個獨一無二的字符串來描述你的數據類型。返回的類型必須包含兩種形式,一種是單一項目,另一種是所有的項目,如下所示:
❑ 單一項目
vnd.<companyname>.cursor.item/<contenttype>
❑ 所有的項目
vnd.<companyName>.cursor.dir/<contenttype>
接下來的代碼片段顯示瞭如何重寫 getType 方法來一句傳入的 URI 來返回正確的 MIME 類型:
@Override
public String getType(Uri _uri)
{
switch (uriMatcher.match(_uri))
{
case ALLROWS: return “vnd.paad.cursor.dir/myprovidercontent”;
case SINGLE_ROW: return “vnd.paad.cursor.item/myprovidercontent”;
default: throw new IllegalArgumentException(“Unsupported URI: “ + _uri);
}
}
註冊 Provider
一旦完成了 Content Provider ,你必須將其添加到應用程序的 manifest 中。使用 authorities 標籤來指定它的路徑,如下面的 XML 片段所示:
<provider android:name=”MyProvider” android:authorities=”com.paad.provider.myapp”/>