Android四大元件之ContentProvider篇

HFW發表於2019-03-17

引言

上篇文章總結了BroadcastReceiver,這篇文章來複習下四大元件的最後一個ContentProvider,ContentProvider能將應用程式內部儲存的資料通過其所提供的訪問方式分享給其它應用程式使用,讓我們先來看看系統提供的ContentProvider

一、系統提供的ContentProvider

系統提供了各式各樣的ContentProvider,比如通訊錄、簡訊等等,這裡我們以獲取通訊錄中聯絡人資訊為例

data class Contact(val id: Int, val name: String, val phone: String)

private fun getContacts(): List<Contact> {
    val cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null,
            null, null, null)
    val contacts = ArrayList<Contact>()
    if (cursor != null) {
        while (cursor.moveToNext()) {
            val id = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID))
            val name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
            // 再根據ID查出電話
            val phoneCursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null)
            if (phoneCursor != null) {
                while (phoneCursor.moveToNext()) {
                    val phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(
                            ContactsContract.CommonDataKinds.Phone.NUMBER))
                    contacts.add(Contact(id, name, phoneNumber))
                }
                phoneCursor.close()
            }
        }
        cursor.close()
    }
    return contacts
}
// 所需許可權
<uses-permission android:name="android.permission.READ_CONTACTS" />
複製程式碼

這裡先通過contentResolver.query查詢出id和name,然後再根據id去另一張表中查詢phoneNumber

二、自定義ContentProvider

我們需要建立一個ContentProvider的子類,重寫以下幾個方法

  • onCreate 在應用程式啟動時會呼叫,因為其執行在主執行緒所有不能執行耗時任務,不然可能會使程式啟動過慢,或者直接ANR
  • insert 在子執行緒執行,外界呼叫ContentResolver.insert時呼叫
  • query 在子執行緒執行,外界呼叫ContentResolver.query時呼叫
  • update 在子執行緒執行,外界呼叫ContentResolver.update時呼叫
  • delete 在子執行緒執行,外界呼叫ContentResolver.delete時呼叫
  • getType 如果該Uri表示一條記錄返回值應該以vnd.android.cursor.item開頭,多條記錄返回值應該以vnd.android.cursor.dir/開頭

然後再在清單檔案中進行配置

<provider
    android:authorities="com.hfw.provider"
    android:exported="true"
    android:name=".MyProvider"/>
複製程式碼

這裡的主機名確定了什麼Uri能夠呼叫該ContentProvider,比如這裡設定了com.hfw.provider,那麼只有以content://com.hfw.provider開頭的Uri才會呼叫該ContentProvider,主機名後面還可以跟上要操作的表明、或者某些條件(自己約定好就行)

  • 例如 content://com.hfw.provider/user 表示要操作User表中所有的資料、content://com.hfw.provider/user/zhangsan 表示要操作User表中name為zhangsan的記錄

相關文章