Mms模塊ConversationList流程分析(1)


一 代碼位置結構及相關類

..\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實現步查詢原理過程在此不作詳細分析;

涉及到線程、HandleMessage

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:.....">

                   //聯系人快捷標識 顯示一張聯系人圖片 點擊彈出相關功能:tellmsg

    <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)




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM