Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 異步查詢框架AsyncQueryHandler的使用

Android 異步查詢框架AsyncQueryHandler的使用

編輯:關於Android編程

AsyncQueryHandler簡介:

異步的查詢操作幫助類,可以處理增刪改(ContentProvider提供的數據)

使用場景:

在一般的應用中可以使用ContentProvider去操作mysql" target="_blank" title="MySQL知識庫">數據庫。

這在數據量很小的時候是沒有問題的,但是如果數據量大了,可能導致UI線程發生ANR異常(超過5秒)。

當然你也可以寫個Handler去做這些操作,只是你每次使用ContentProvider時都要再寫個Handler,必然降低了效率。

因此當數據量較大時,最好還是使用Android已經封裝好的異步查詢框架AsyncQueryHandler,優化我們的代碼.

要注意的是,一般在查詢本地的應用的數據的時候要去采用CursorAdapter

AsyncQueryHandler內部實現

AsyncQueryHandler類封裝了調用者線程與工作線程的交互過程。交互的主體是兩個Handler,一個運行在調用者線程中,一個運行在工作者線程中。通過提供onXXXComplete的回調接口,實現事件的完成處理。

API中提供

startInsert,

startDelete,

startUpdate,

startQuery四種方法,並有響應的onXXXComplete()方法.於對應的4個onXXXComplete()方法都是空實現,因此我們完成相應調用後進行後續其他的操作.

使用方法

繼承AsyncQueryHandler類,並提供onXXXComplete方法的實現(可以實現任何一個或多個,當然你也可以一個也不實現,如果你不關注操作數據庫的結果),在你的實現中做一些對數據庫操作完成的處理。

使用時直接調用startXXX方法即可。傳入的通用參數如下:

token,一個令牌,主要用來標識查詢,保證唯一即可.需要跟onXXXComplete方法傳入的一致。(當然你也可以不一致,同樣在數據庫的操作結束後會調用對應的onXXXComplete方法)。當你使用很多次查詢的時候,這個值就相當於綁定了你的查詢方法。

cookie,你想傳給onXXXComplete方法使用的一個對象。(沒有的話傳遞null即可)

Uri uri(進行查詢的通用資源標志符):

projection 查詢的列

selection 限制條件

selectionArgs 查詢參數

orderBy 排序條件

下面簡單介紹一下查詢操作,如果查詢操作熟悉了,其他的也就迎刃而解了。

例如,我要查詢一下我手機裡面有多少視頻文件,以及對應的視頻文件的名稱、視頻占用內存、視頻時長,以及路徑。按照以往的方式,我們會這麼寫:

 

 List videoDatas = new ArrayList();
		
		/*//參數:url、查詢哪些列、選擇條件占位符、選擇條件占位符?用什麼替換、查詢後排序方式
		Cursor cursor = context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, 
				new String[]{Media.TITLE,//視頻名稱
				Media.SIZE,Media.DURATION,Media.DATA},//大小、時長、視頻路徑
				null, null, null);
		while(cursor.moveToNext()){
			VideoInfo videoInfo = new VideoInfo();
			String title = cursor.getString(cursor.getColumnIndex(Media.TITLE));
			int size = cursor.getInt(cursor.getColumnIndex(Media.SIZE));
			int duration = cursor.getInt(cursor.getColumnIndex(Media.DURATION));
			String path = cursor.getString(cursor.getColumnIndex(Media.DATA));;
			
			videoInfo.setDuration(duration);
			videoInfo.setPath(path);
			videoInfo.setSize(size);
			videoInfo.setTitle(title);
			videoDatas.add(videoInfo);
		}

很顯然,以前的方式就是內容提供者查詢數據庫操作。外界如果想要獲取這些信息,是需要開啟Handler---Thread的,如下:

 

 

new Thread(new Runnable() {
			
			@Override
			public void run() {
				// 獲取數據
				videDatas = MediaInfoEngine.getVideoInfo(UIUtils.getContext());
				UIUtils.runOnUiThread(new Runnable() {
					
					@Override
					public void run() {
						adapter.notifyDataSetChanged();
					}
				});
			}
		}).start();
這樣就獲取到了手機所有視頻文件信息了。但是,如果你手機裡有1萬條視頻文件,這個時候,即使使用這種方式,估計上邊業報ANR了。這個時候,AsyncQueryHandler幫我們解決很多問題,因為它已經自動幫我們封裝了子線程。提供子線程DB操作,然後回調到主線程UI操作。寫法如下:

 

 

AsyncQueryHandler queryHandler = new AsyncQueryHandler(context.getContentResolver()) {
			/**查詢的響應回調*/
			@Override
			protected void onQueryComplete(int token, Object cookie,
					Cursor cursor) {
				if(token == 1){
					while(cursor.moveToNext()){
						VideoInfo videoInfo = new VideoInfo();
						String title = cursor.getString(cursor.getColumnIndex(Media.TITLE));
						int size = cursor.getInt(cursor.getColumnIndex(Media.SIZE));
						int duration = cursor.getInt(cursor.getColumnIndex(Media.DURATION));
						String path = cursor.getString(cursor.getColumnIndex(Media.DATA));;
						
						videoInfo.setDuration(duration);
						videoInfo.setPath(path);
						videoInfo.setSize(size);
						videoInfo.setTitle(title);
						videoDatas.add(videoInfo);
					}
				}
			}
		};
		
		/**啟動異步查詢*/
		//參數一:請求碼
		queryHandler.startQuery(1, null, Media.EXTERNAL_CONTENT_URI, 
				new String[]{Media.TITLE,//視頻名稱
				Media.SIZE,Media.DURATION,Media.DATA},//大小、時長、視頻路徑
				null, null, null);
具體的參數,在開篇就介紹的很詳細了。簡單說一下如何操作的:首先執行開始查詢操作startQuary(),這個方法給我們封裝好了,是在子線程執行的,在它內部自定查詢完畢後會生成一個curssor對象,回調內部類裡面的onQueryComplete方法,這個方法的三個參數分別是:1:請求碼(可以想一下intent隱式啟動的那個請求碼的意思)2:執行startQuary()時候,第二參數。一般傳入null,但是有時候會是某個對象(場景:AsyncQueryHandler與CursorAdapter結合使用的時候,這裡就可以傳入一個curssorAdapter對象,在回到方法裡面就可以接收這個對象。回想message的obj字段)3:startQuary()方法查詢數據庫後所有返回的結果游標。接下來就很簡單了,遍歷cursor保存數據即可了。

這個時候,我們獲取數據的時候,也就不用自己開啟線程了。直接獲取即可,如下:

 

 // 獲取數據,不用再開啟你子線程了
		videDatas = MediaInfoEngine.getVideoInfo(UIUtils.getContext());
		adapter.notifyDataSetChanged();
這裡我沒有用到CursorAdapter,因為實際開發中,也沒怎麼用到這個適配器。後續博客會再對這個適配器做詳細的介紹。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved