一 代碼位置結構及相關類
..\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中聯系人數據添加