一 代码位置结构及相关类
..\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中联系人数据添加