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)



原文地址:https://www.cnblogs.com/bastard/p/2429092.html