一 代碼位置結構及相關類
..\packages\apps\Mms\src\com\android\mms\ui:存放介面顯示相關的類
..\packages\apps\Mms\src\com\android\mms\data:存放介面顯示需要的資料相關的類
主要的類:
ConversationList:資訊對話介面——>ListActivity
ConversationListAdapter:適配器 ——>CursorAdapter
ConversationListItem:對話介面的ListItem View——>RelativeLayout
ConversationListItemData:對話介面列表顯示需要的各項資料
Conversation:顯示所需所有對話資訊的所有資料
ContactList:每個Thread資訊所對應的連絡人
Contact:一個連絡人資料資訊
二 互動過程:
介面顯示資料擷取過程:
類互動過程:
二 介面資料查詢更新流程圖
三 代碼實現過程分析
1 ConversationList中啟動查詢
onStart(){
……
startAsyncQuery();
}
實際上是:
startAsyncQuery() {
……
// mQueryHandler——>ThreadListQueryHandler ConversationList的內部類
//最終繼承於AsyncQueryHandler
Conversation.startQueryForAll(mQueryHandler, THREAD_LIST_QUERY_TOKEN);
}
2 Conversation中調用非同步查詢線程
Conversation.startQueryForAll——>
public static void startQueryForAll(AsyncQueryHandler handler, int token) {
……
final AsyncQueryHandler queryHandler = handler;
queryHandler.postDelayed(new Runnable() {
//匿名內部類
public void run() {
queryHandler.startQuery(
queryToken, null, sAllThreadsUri,
ALL_THREADS_PROJECTION, null, null, Conversations.DEFAULT_SORT_ORDER);
}
}, 10);
Conversations.DEFAULT_SORT_ORDER);
}
(AsyncQueryHandler使用條用者線程和背景工作執行緒組成)非同步查詢
此查詢的是:所有Thread資訊;
3 AsyncQueryHandler中查詢過程
//各參數的含義
public void startQuery(int token, Object cookie, Uri uri,
String[] projection, String selection, String[] selectionArgs,
String orderBy) {
//啟動一個工作者線程
mWorkerThreadHandler.sendMessage(msg);
}
——》背景工作執行緒查詢完畢之後,返回到調用者線程;
——》執行AsyncQueryHandler的onQueryComplete函數;
——》 回到自行實現的繼承於AsyncQueryHandler的類中 重寫的onQueryComplete函數中;
——》執行到ThreadListQueryHandler的onQueryComplete函數中;
——》通知到ConversationList,至此查詢Thread資訊的過程結束;
資料據查詢就是要使ContentProvider與資料庫進行互動
在AsyncQueryHandler的內部類工作者線程WorkerHandler的函數handleMessage中完成;
AsyncQueryhandler:
A helper class to help make handling asynchronous ContentResolver queries easier.
AsyncQueryhandler中有兩個handlerMessage,
一個是基於外部線程looper的,
一個是基於內部WorkerHandler實現的HandlerThread新線程的looper。
外部調用startQuery會通過mWorkerThreadHandler.sendMessage(msg)將查詢發送給
WorkerHandler中處理,即在新線程中查詢,
當WorkerHandler處理完後,把結果發送給AsyncQueryhandler的handlerMessage來調用對應的onXXXComplete函數。
這裡就是把查詢結果返回給原來線程來處理,這就通過兩個handlerMessage實現了兩個線程的訊息互動。
AsyncQueryHandler實現步查詢原理過程在此不作詳細分析;
涉及到線程、Handle,Message等
ContentProvider如何與資料庫進行互動在此不作詳細分析;
4 ThreadListQueryHandler
屬於ConversationList類的內部類:繼承於AsyncQueryHandler;
重寫抽象函數,接收查詢結果的反饋;
簡單看一下這個函數:
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch (token) {
case THREAD_LIST_QUERY_TOKEN:
……
// mListAdapter屬於ConversationListAdapter
mListAdapter.changeCursor(cursor); //更新UI資料
}
}
——》至此工作將轉移到ConversationListAdapter中進行;
——》產生所需要ViewIten和綁定UI顯示所需要的資料;
ConversationListAdapter繼承於CursorAdapter;
關於CursorAdapter功能及實現原理作用在此不作詳細分析;
5 ConversationListAdapter
繼承於:CursorAdapter;
簡單看一下:ListView於Adapter以及Cursor的關係:
Adapter的作用就是ListView介面與資料之間的橋樑,
當列表裡的每一項顯示到頁面時,都會調用Adapter的getView方法返回一個View
(對於CursorAdapter具體作用這裡不作詳細分析)
看一下CursorAdapter中的getView函數:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
……
View v;
//這裡的作用很關鍵 決定要不要新建立一個ViewItem
if (convertView == null) {
//建立一個ViewItem
v = newView(mContext, mCursor, parent);
} else {
//涉及到Recycler機制 保證不會無限去建立Item,重複利用
v = convertView;
}
//將資料分配給所要顯示的ViewItem
bindView(v, mContext, mCursor);
return v;
}
兩個抽象函數abstract
newView:返回一個View,自訂ViewItem,需要重寫;
bindView:綁定資料,需要重寫;
下面看看 ConversationListAdapter對這兩個函數的實現:
newView:
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// LayoutInflater擷取res\layout\下的布局檔案xml,並且執行個體化;
//這裡就是ListViewItem
return mFactory.inflate(R.layout.conversation_list_item, parent, false);
}
(具體LayoutInflater的作用在此不詳細分析)
看看conversation_list_item的布局:
<com.android.mms.ui.ConversationListItem xmlns:android="http:.....">
//連絡人快捷標識 顯示一張連絡人圖片 點擊彈出相關功能:tell,msg
<android.widget.QuickContactBadge android:id="@+id/avatar"/>
//ViewItem可以容納的控制項
<ImageView android:id="@+id/presence"/>
<TextView android:id="@+id/from"/>
<TextView android:id="@+id/date"/>
<ImageView android:id="@+id/error"/>
<ImageView android:id="@+id/attachment"/>
<TextView android:id="@+id/subject"/>
</com.android.mms.ui.ConversationListItem>
bindView:
@Override
public void bindView(View view, Context context, Cursor cursor) {
//轉化為資訊列表的ListViewItem
ConversationListItem headerView = (ConversationListItem) view;
//使用cursor構建對話資訊 關聯資訊資料和連絡人資料
Conversation conv = Conversation.from(context, cursor);
//構建單個對話資訊資料
ConversationListItemData ch = new ConversationListItemData(context, conv);
//綁定資料
headerView.bind(context, ch);
}
根據cursor所擷取到的資料個數 迴圈構建;
待續下一篇:Thread中連絡人資料添加
Mms模組ConversationList流程分析(2)