Android必知必會的四大元件 -- ContentProvider篇

ClericYi發表於2020-02-25

Android必知必會的四大元件 -- ContentProvider篇

前言

作為四大元件之一,它的地位絕對不容許輕視的。但是我們在哪裡有用到過他呢?其實很簡單,你在使用app時,是不是經常的會詢問你是否開啟通訊錄的訪問,如果你同意了,這個時候ContentProvider就發揮了他的作用。

思維導圖

Android必知必會的四大元件 -- ContentProvider篇

使用方法

以下通過對通訊錄的操作讓讀者來更清晰的瞭解。 但是共享的資料不應該被我們隨意的更改,如果有這樣的需要,把這些資料儲存在本地,然後再進行這樣的操縱更為合適,所以下方的演示程式碼只包含了查詢的功能。不過因為呼叫外部的資料,一般來說需要許可權申請。

我已經在Android工具包中已經整合了許可權申請的工具類。

// 資料查詢
try (Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null)) {
        while (cursor.moveToNext()) {
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                Log.e(TAG, name + " ;" + number);
            }
} catch (Exception e) {
            e.printStackTrace();
}
複製程式碼

檔案共享的基礎

其實在ContentProvider中使用的通訊機制依舊是Binder,而檔案定位則是通過URI的方式來完成,所以主講的一部分內容就是URI的格式解析。

URI

格式:[scheme:][//host:port][path][?query]
複製程式碼

這一個URI的格式,為了方便起見,我們直接拿一個域名來分析它。

》》例題《《

連結地址:juejin.im/user/5e2659…

  1. scheme:https,也就是協議
  2. host:juejin.im,域名地址
  3. port:預設80,埠號
  4. path:/user/5e2659e15188254d95242d4b,檔案路徑/控制器路徑
  5. query:比如 ?userId=x&message=y,就是我們javaWeb中的一些請求資料。

當然在我們的ContentProvider存在一定的偏差。

檔案位置:content://com.clericyi.file/message/id

  1. scheme:content://,這是Android的固定路徑
  2. authority:com.clericyi.file,也就是用於標示唯一的ContentProvider
  3. path:message,也就是對應的表名
  4. id:對應表中的資料

幫助工具

UriMatcher

這是一個內建的URI工具,他一共只提供了兩個開放方法addURI()match(),這是一個用於幫助匹配ContentProviderURI的方法,針對的是除去id前半段匹配。

// 用法
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
String authority = "com.clericyi.file";
String path = "message";
int URI_CODE = 1;
// 將URI和URI_CODE關聯
uriMatcher.addURI(authority, path, URI_CODE);
// 用於獲取對應的URI_CODE
uriMatcher.match(Uri.parse("content://com.clericyi.file/message"))
複製程式碼

ContentUris

同樣是一個內建的工具類,提供的方法有parseId()appendId()withAppendedId()removeId(),針對的就是id

Uri uri = Uri.parse("content://com.clericyi.file/messag");
// 連線id
uri = ContentUris.withAppendedId(uri, CODE);
// 去除id
uri = ContentUris.removeId(uri);
// 獲取id
long num = ContentUris.parseId(uri);
複製程式碼

ContentProvider程式碼流程導讀

工作流程:

從上文中的電話簿號碼查詢入手
(1)獲取一個ContentResolver,並呼叫query(),內部引數很多,基本和資料庫查詢的引數保持一致。
(2)在query()方法中會呼叫到acquireUnstableProvider(uri)的方法,而返回值IContentProvider,對應就是一個Binder機制
(3)內部通過對uri的一些解析,找得到對應的檔案,然後轉化成Cursor遊標
(4)通過遊標的滑動讀取,就轉化成了我們的資料
複製程式碼

query()內部引數分析

  • uri:位置暴露的唯一表示。
  • projection:返回列(欄位)
  • selection:設定條件,相當於資料庫中的where
  • selectionArgs:和selection聯合使用,用於替換selection中的 ?
  • sortOrder:排列順序,相當於資料庫中的order by
全部引數使用例項:
contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI
    , new String[]{android.provider.ContactsContract.Contacts.DISPLAY_NAME}
    , android.provider.ContactsContract.Contacts.DISPLAY_NAME + "=?"
    , new String[]{"小易"}
    , android.provider.ContactsContract.Contacts.DISPLAY_NAME + " DESC"); // 中間存在空格,預設為ASC,升序。
複製程式碼

最後的話這片文章就不寫關於聯合Database的使用了,應該容易冗長,專門找了一篇文章給讀者們拿來專門學習ContentProvider的使用。跳轉連結

另外也算是我的一種突破,畢竟一天發了四篇部落格,雖然兩篇其實我只是重構了一下,但是著實還是有點累的。

以上就是我的學習成果,如果有什麼我沒有思考到的地方或是文章記憶體在錯誤,歡迎與我分享。


相關文章推薦:

Android必知必會的四大元件 -- Activity篇

Android必知必會的四大元件 -- Broadcast Receiver篇

Android必知必會的四大元件 -- Service篇

相關文章