ContentProvider 內容提供器
什麼是內容提供器
官方解釋:
A content provider manages access to a central repository of data. A provider is part of an Android application, which often provides its own UI for working with the data. However, content providers are primarily intended to be used by other applications, which access the provider using a provider client object. Together, providers and provider clients offer a consistent, standard interface to data that also handles inter-process communication and secure data access.
通俗易懂:
主要是用於不同的應用程序之間實現數據共享的功能.
內容提供器以一個或多個表(跟數據庫的表類似)的形式呈獻給外部應用.
分兩類:
使用現有的內容提供器來讀取和操作應用程序的數據
創建自己的內容提供器提供外部訪問接口
ContentProvider的基本用法
訪問其他程序的數據
ContentResolver類
如果想要訪問內容提供器中共享的數據, 就需要藉助ContentResolver類, 可以通過Context.getContentResolver()方法來獲取該類的實例.
這個ContentResolver提供了一些對數據進行CRUD的操作, 也就是常說的”增刪查改”
但是, 與SQLiteDatabase不同的是, ContentResolver的增刪查改方法是不接受表名參數的,而是 Uri,
Uri: 由 權限 和 路徑 組成的. (用於在提供程序中標識數據的URI)。
Uri的標準寫法如下:
content://com.example.app.provider/table1
table1爲數據庫的名字;
再使用Uri.parse(uri) 就可以將字符串轉發爲Uri類型啦.
說了那麼多,我們還沒開始訪問數據, 代碼如下:
Cursor cursor=getContentResolver().query( uri, projection, selection, selectionArgs, sortOrder );
上面傳入參數很多, 下面表格將這些參數和SQLiteDatabase中的query()進行了對比:
query() 對應SQL部分 描述 uri from table_name 指定查詢應用程序的某一個表 projection select column1,column2 指定查詢的列名 selection where column=value 爲where中的佔位符提供具體的值 selectionArgs - 爲where的佔位符提供具體的值 sortOrder order by column1, column2 指定查詢結果的排序方式 很明顯上面返回的是Cursor類, 讀取數據的思路就是通過移動遊標的位置來遍歷Cursor的所有行, 然後取出每一行相應列的數據, 代碼如下:
if(cursor!=null){ while(cursor.moveToNext()){ String column1 = cursor.getString(cursor.getColumnIndex("column1")); int column2 = cursor.getInt(cursor.getColumnIndex("column2")); } cursor.close(); }
以下是各種操作的簡單介紹:
ContentValues values=new ContentValues(); //插入數據 getContentResolver().insert(uri, values); //更新數據 getContentResolver().update(uri, values, "column1 = ? and column2 = ?", new String[]{"text","1"}); //刪除數據 getContentResolver().delete(uri, "column2 = ?", new String[]{"1"});
創建自己的ContentProvider
創建前的準備
決定你是否需要ContentProvider
你想爲其他應用提供複雜的數據或文件
你想允許用戶將複雜的數據從你的應用複製到其他應用中
你想使用搜索框架提供自定義搜索建議
創建步驟
設計原始存儲, 文件數據(照片\音頻…)或者結構化數據(數據庫或數組…)
繼承ContentProvider類, 並實現具體方法
定義提供程序的授權字符串\ URI \ 列名稱
添加其他可選的部分
實例操作
創建數據庫, 這裏不詳細介紹了.
繼承ContentProvider類
public class DemoContentProvider extends ContentProvider { @Override public boolean onCreate() { return false; } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return null; } @Nullable @Override public String getType(@NonNull Uri uri) { return null; } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { return null; } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } }
設計內容URI
設計授權
如果Android包名爲com.example., 則爲提供程序提供com.example..provider 授權
設計路徑結構
合併上一段的權限來生成內容URI : com.example..provider/table1 或者table2
處理內容URI ID
末尾有_ID值就是來對錶的單個行的訪問.
URI模式
由於有實用類UriMatcher, 所以可以使用以下通配符來匹配內容:
” * ” : 匹配任意長度的任意字符
” # ” : 匹配任意長度的數字
標準的URI:
content://com.example.app.provider/….
綜合代碼如下:
public class DemoContentProvider extends ContentProvider { private static final int TABLE1_DIR = 0; private static final int TABLE1_ITEM = 1; private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sUriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR); sUriMatcher.addURI("com.example.app.provider", "table1/#", TABLE1_ITEM); } @Override public boolean onCreate() { return false; } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = null; switch (sUriMatcher.match(uri)) { case TABLE1_DIR: //查詢table1表中的所有數據 break; case TABLE1_ITEM: //查詢table1表中的單條數據 break; default: break; } return cursor; } @Nullable @Override public String getType(@NonNull Uri uri) { switch (sUriMatcher.match(uri)) { case TABLE1_DIR: return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1"; case TABLE1_ITEM: return "vnd.android.cursor.item/vnd.com.example.app.provider.table1"; default: break; } return null; } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { return null; } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } }
不知道大家有沒有看到getType這個方法,返回了一些莫名其妙的字符串
其實這些都是MIME類型的數據
格式如下:
- 必須vnd開頭
- 路徑結尾的話就後接android.cursor.dir/ , 若是id結尾就接android.cursor.item/
- 最後接上 vnd. < authority > . < path >
總結
這個內容提供器有很多demo , 需要結合數據庫來講, 我想等講完數據庫再上傳這個DEMO吧.謝謝大家看我的學習筆記!