Android四大元件之ContentProvider(二)
阿新 • • 發佈:2018-11-23
上節提到的四大元件之ContentProvider的簡單使用,在這篇文章中詳細的介紹其中的一些方法。
1.String getType(Uri uri)
方法
首先看看官方對它的解釋:
/** * Implement this to handle requests for the MIME type of the data at the * given URI. The returned MIME type should start with * <code>vnd.android.cursor.item</code> for a single record, * or <code>vnd.android.cursor.dir/</code> for multiple items. * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes * and Threads</a>. * * <p>Note that there are no permissions needed for an application to * access this information; if your content provider requires read and/or * write permissions, or is not exported, all applications can still call * this method regardless of their access permissions. This allows them * to retrieve the MIME type for a URI when dispatching intents. * * @param uri the URI to query. * @return a MIME type string, or {@code null} if there is no type. */ public abstract @Nullable String getType(@NonNull Uri uri);
本人英文小白,大家可以自行百度翻譯;我自己的理解是:
給定一個Uri返回相對應的MIME型別;注意,應用程式不需要許可權;如果您的內容提供者需要讀取和/或寫許可權,或不匯出,所有應用程式仍然可以呼叫此方法不考慮其訪問許可權。這使他們在排程意圖時檢索URI的MIME型別。
返回MIME型別有何要求:
- 以
vnd.android.cursor.dir/
或者vnd.android.cursor.item/
開頭,根據Uri判斷是處理單條資料還是全部資料 - 後接
vnd.< aothority >.< path>
結尾
例:uri = “content://org.wdl.provider/books”
返回的MIME為:vnd.android.cursor.dir/vnd.org.wdl.provider.books
MIME的內容見:(https://blog.csdn.net/qq_34341338/article/details/82997517)
作用:
-
隱式的啟動activity等,通過IntentFliter匹配
-
結合
query(Uri, String[], String, String[], String)
這個方法來解釋一下:在該方法中,返回一個Cursor遊標物件。而Cursor中是單條的記錄還是一個集合,需要和在getType()方法中返回的型別保持一致。當返回的 MIME型別是Xxx.CONTENT_ITEMS時,Cursor應該是一個集合;當返回的MIME型別是 Xxx.CONTENT_ITEM時,Cursor應該是單條記錄。
由於在getType()方法裡面,我們顯示的返回了android平臺可以識別的MIME型別,所以在
執行query()方法返回Cursor物件的時候,系統將不需要再進行驗證
,從而可以說是節省了系統開銷
。
2.getContext().getContentResolver().notifyChange(uri, null)
仔細觀察前面ContentProvider的使用時,發現在insert,update,delete後都會呼叫該方法通知所有註冊在該Uri上的監聽者。而為了提供監聽ContentProvider資料的改變
,Android提供了ContentObserver基類
。
如何使用?
- 自定義監聽類繼承自ContentObserver
- 重寫
onChange()
方法,當被監聽的ContentProvider資料改變時,會回撥onChange()方法 - 註冊監聽器,ContentResolver向指定的Uri註冊監聽器,方法:
registerContentObserver(Uri uri,boolean notifyForDescendents,ContentObserver observer)
:
-
uri
:ContentProvider的Uri -
notifyForDescendents
:當值為true
時,假如監聽的Uri為content://abc,那麼Uri為content://abc/xyz或者content://abc/xyz/fox的資料改變時也會觸發該監聽器;值為false則只有Uri為content://abc的資料改變時才會觸發 -
observer
:監聽器例項
使用:
package com.wdl.contentproviderclient
import android.content.ContentResolver
import android.content.ContentUris
import android.content.ContentValues
import android.content.Intent
import android.database.ContentObserver
import android.net.Uri
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
import java.lang.StringBuilder
class MainActivity : AppCompatActivity() {
lateinit var resolver:ContentResolver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
resolver = contentResolver
//註冊該URI的監聽
resolver.registerContentObserver(Uri.parse("content://sms"),true,
SmsObserver(resolver,null))
btnQuery.setOnClickListener {
val intent = Intent("com.wdl.mime")
intent.data = Books.Book.BOOKS_CONTENT_URI
startActivity(intent)
val cursor = resolver.query(Books.Book.BOOKS_CONTENT_URI
,null,"price=?", arrayOf("50.2"),null)
//cursor.close()
val stringBuilder = StringBuilder()
while (cursor.moveToNext()){
val id = cursor.getInt(cursor.getColumnIndexOrThrow(Books.Book.ID))
val name = cursor.getString(cursor.getColumnIndexOrThrow(Books.Book.NAME))
val price = cursor.getInt(cursor.getColumnIndexOrThrow(Books.Book.PRICE))
stringBuilder.append("id=$id,name=$name,price=$price \n")
}
cursor.close()
Log.e("wdl",stringBuilder.toString())
}
btnDelete.setOnClickListener {
//val index = contentResolver.delete(uri,null,null)
val index = resolver.delete(Books.Book.BOOKS_CONTENT_URI,"price=?", arrayOf("55.2"))
Log.e("wdl",""+index)
}
btnInsert.setOnClickListener {
val value = ContentValues()
value.put(Books.Book.NAME,"smwdl")
value.put(Books.Book.PRICE,50.2)
val uri = resolver.insert(Books.Book.BOOKS_CONTENT_URI,value)
Log.e("wdl",uri.toString())
}
btnUpdate.setOnClickListener {
val value = ContentValues()
value.put(Books.Book.PRICE,55.2)
val uri = ContentUris.withAppendedId(Books.Book.BOOK_CONTENT_URI,1)
val index = resolver.update(uri
,value,"name like ?", arrayOf("smwdl"))
Log.e("wdl",""+index)
}
}
private class SmsObserver constructor(val resolver: ContentResolver, handler: Handler?): ContentObserver(handler) {
//資料更改時回撥此方法
override fun onChange(selfChange: Boolean) {
val cursor = resolver.query(Uri.parse("content://sms/inbox"),null
,null
,null
,null)
while (cursor.moveToNext()){
val builder = StringBuilder()
builder.append("address=${cursor.getString(cursor.getColumnIndexOrThrow("address"))},")
.append("subject=${cursor.getString(cursor.getColumnIndexOrThrow("subject"))}")
.append("body=${cursor.getString(cursor.getColumnIndexOrThrow("body"))}")
.append("time=${cursor.getLong(cursor.getColumnIndexOrThrow("date"))}")
Log.e("wdl",builder.toString())
}
cursor.close()
}
}
}
3.批量操作資料
未完待完成。。。。。。