好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Mms模块ConversationList流程分析

Mms模块ConversationList流程分析

一 代码位置结构及相关类

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

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于Mms模块ConversationList流程分析的详细内容...

  阅读:38次