Android開發--詳解ContentProvider/Cursor的使用
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
ContentProvider是Android四大元件之一,所以如果是自己實現ContentProvider,需要在AndroidManifest.xml檔案中進行宣告,幸運的是,我們很少需要自己定義實現它,一般我們的開發只需要用到系統自己提供的ContentProvider,使用起來非常方便。
首先來讓我們認識ContentProvider:
基本概念:
1.ContentProvider提供為儲存和獲取資料提供了統一的介面
2.使用ContentProvider可以在不同的應用程式之間共享資料
3.Android為常見的一些資料提供了ContentProvider
下面我開始介紹實現ContentProvider的過程:
1.定義一個CONTENT_URI常量
2.定義一個雷,繼承自ContentProvider
3.實現query,insert,update,delete,getType和onCreate方法
4.在AndroidManifest.xml檔案中進行宣告
ContentProvider提供了一系列的函式,當自己實現ContentProvider需要實現這些方法:
1.query()
2.insert()
3.update()
4.delete()
5.getType()
6.onCreate()
接下來詳細介紹ContentProvider:
*一.初識Content Provider
* 1.簡介
* 1.1 Content Provider實現了一組通用的方法來提供資料的增刪改查的功能
* 1.2 客戶端通常不會直接使用這些方法,大多數都是通過ContentResolver物件實現對Content Provider的操作
* 1.3 開發一般會通過呼叫方法獲得ContentProvider物件
* 例如:ContentResolver cr=getContentResolver
* 使用ContentResolver提供的方法可以獲得ContentProvider中任何感興趣的物件
* 2.資料模型
* 2.1 ContentProvider使用基於資料庫模型的簡單表格來提供其中的資料,其中每一行都代表一個記錄,
* 每一列代表特定型別和含義的資料,其中每條記錄包含一個數值型的_ID欄位,用於在表格中唯一標識該記錄
* 注意:ID欄位前還包含了一個下劃線
* 2.2 查詢返回一個Cursor物件,它能遍歷各行各列來讀取每個欄位的值。對於各個型別的資料,Cursor物件都提供了
* 專用的方法,因此,為了讀取欄位的資料,開發人員必須要知道當前欄位包含的資料型別
* 注意:Cursor的使用方法:通過查詢,它會指向第一個記錄之前,所以需要開發者moveToNext,且查詢欄位的動作是
* 先指向某一條記錄,即指向某一行,再從某一列或多列中取得資料,且需要知道資料型別(列資料),例如:
* int id=cursor.getInt(idIndex);
* String name=cursor.getString(displayNameIndex);
* 3.URI的用法
* 3.1 每個Content Provider提供公共的URI(使用Uri類包裝)來唯一標識其資料集。管理多個數據集(多個表格)的
* Content Provider為每個都提供了單獨的URI,且URI的標識有固定的格式
* 3.2 UIR常量用於所有與Content Provider的互動中,每個ContentResolver方法使用URI作為第一個引數,它標識
* ContentResolver應該使用哪個provider以及其中的哪個表格
* 二.詳解Content Provider
* 1.系統預定義的Content Provider
* 1.1 Android系統為常用資料型別提供了很多預定義的Content Provider(聲音,視訊,圖片,聯絡人等),它們大都位於
* android.provider包中
* 1.2 Android系統提供的常見Content Provider說明如下:
* Browser:讀取或修改書籤,瀏覽歷史或網路搜尋
* CallLog:檢視或更新通話歷史
* Contacts:獲取,修改或儲存聯絡人資訊
* LiveFolders:由Content Provider提供內容的特定資料夾
* MediaStore:訪問聲音,視訊和圖片
* Setting:檢視和獲取藍芽設定,鈴聲和其他設定偏好
* SearchRecentSuggestions:該類能為應用程式建立簡單的查詢建議提供者
* SyncStateContract:用於使用資料陣列賬號關聯資料的ContentProvider約束
* UserDictionary:在可預測文字輸入時,提供使用者定義的單詞給輸入法使用
* 2. 查詢資料
* 2.1 在Content Provider中查詢資料,開發人員需要知道一下資訊:
* 標識該Content Provider的URI
* 需要查詢的資料欄位名稱
* 欄位中資料的型別
* 如果需要查詢特定記錄,那麼還需要知道該記錄的ID值
* 2.2 ContentResolver.query()或Activity.managedQuery()方法都可以完成查詢功能,這兩個方法
* 使用相同的引數,並且都返回Cursor物件。其區別在於managedQuery()方法讓Activity來管理Cursor的
* 宣告週期,而query()方法需要程式設計師自己管理。
* 2.3 query()方法介紹
* 方法的宣告如下:
* public final Cursor query(Uri uri, String[] projection, String selection,
* String[] selectionArgs, String sortOrder)
* uri:用於查詢的Content Provider的URI值
* projection:由需要查詢的列名組成的陣列,如果為null則表示查詢全部列
* selection:類似SQL中的WHERE子句,用於增加條件來完成資料過濾
* selectionArgs:用於替換selection中可以使用?表示的變數值
* sortOrder:用於實現排序功能
* 返回值:Cursor物件,它位於第一條記錄之前,或者為null
* 2.4 利用遊標工具進行查詢時,注意是兩次查詢,首先到達的那條記錄的行
* 第一次查詢找到需要資料的那一列,第二次查詢才是真正從那一列中獲得資料
* 三.總結
* 3.1 Content Provider是Android四大基本元件之一,它主要用於在不同的應用程式之間共享資料
* 3.2 Content Provider使用基於資料庫模型的簡單表格來提供其中的資料,這裡每行代表一條記錄,每列
* 代表特定型別和含義的資料
下面我用一個例子來說明ContentProvider的使用:
我們在開發的過程中經常用到聯絡人的資訊,所以,取得聯絡人的資訊並操縱就顯得很重要,下面的例子就是對聯絡人的資訊進行相關的操作。
下面的截圖是程式的實現:
實現的原始碼如下:
public class Content_Provider_Activity extends Activity { private ListView listView; private ListView listView2; private Button button; /* * 1.靜態常量的定義 * 1.1 各個引數用於選擇的目標,如果在陣列中沒有某個引數,則遊標不會定義(即找到那個引數) * 1.2 從定義可以看出,聯絡人的所有資訊不是定義在一張表之中 * 1.3 為了操作的方便和可行,分開定義查詢的目標 */ public static final String[] COLUMNS={Contacts._ID, Contacts.DISPLAY_NAME}; private static final String[] COLUMNS2={Contacts.DISPLAY_NAME,Contacts._ID}; private static final String[] COLUMNS3={Phone.NUMBER}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_content__provider_); listView=(ListView)findViewById(R.id.listview); listView2=(ListView)findViewById(R.id.listview2); button=(Button)findViewById(R.id.button); button.setText("點選獲取聯絡人姓名和手機號碼"); button.setOnClickListener(new MyButton()); @SuppressWarnings("deprecation") Cursor cursor=managedQuery(Contacts.CONTENT_URI, COLUMNS, null, null, null); //獲取ID所對應的索引值---列索引 int idIndex=cursor.getColumnIndex(COLUMNS[0]); //獲取NAME所對應的索引值---列索引 int displayNameIndex=cursor.getColumnIndex(COLUMNS[1]); List<String> items=new ArrayList<String>(); for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){ int id=cursor.getInt(idIndex); String name=cursor.getString(displayNameIndex); items.add("id="+id+"\t 姓名= "+name); } ArrayAdapter<String> adapter=new ArrayAdapter<String>(Content_Provider_Activity.this, R.layout.list_item,items); listView.setAdapter(adapter); } public class MyButton implements OnClickListener{ @Override public void onClick(View arg0) { // TODO Auto-generated method stub switch (arg0.getId()) { case R.id.button: getNameAndPhone(); break; default: break; } } } public void getNameAndPhone(){ @SuppressWarnings("deprecation") Cursor cursor=managedQuery(Contacts.CONTENT_URI, COLUMNS2, null, null, null); int displayNameIndex=cursor.getColumnIndex(COLUMNS2[0]); List<String> items=new ArrayList<String>(); for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){ String name=cursor.getString(displayNameIndex); int id=cursor.getInt(cursor.getColumnIndex(COLUMNS2[1])); @SuppressWarnings("deprecation") Cursor phone=managedQuery(Phone.CONTENT_URI, null, Phone.CONTACT_ID+" = "+id, null, null); while(phone.moveToNext()){ String phoneNumber=phone.getString(phone.getColumnIndex(COLUMNS3[0])); items.add("姓名:"+name+"\t 手機:"+phoneNumber); } } ArrayAdapter<String> adapter=new ArrayAdapter<String>(Content_Provider_Activity.this, R.layout.list_item ,items); listView2.setAdapter(adapter); }}