Anlyze ConversationList In Qcom
The first UI In MMS is ConversationList
Main flow of loading data
1:在ConversationList的onCreate()函数被调用时,会新建一个异步加载handler, new ThreadListQueryHandler,这个handler里面的新建thread进行异步查询的功能。
2:onStart()调用时会调用到startAsyncQuery()函数,这个函数顾名思义就是与数据查询相关。
3:跳转到了conversation的 StartQuery()函数中, 这里有设置uri,projection,selection,uri= sAllThreadsUri= Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build() projection =ALL_THREADS_PROJECTION(这里几乎返回了thread table中的所有列),selection = null, dort =Conversations.DEFAULT_SORT_ORDER。这里调用的是传进来的handler.StartQuery()。而这个handler就是我们在onCreate()中创建的ThreadListQueryHandler。
PS: 查看AsyncQueryHandler的时候注意理清thread,handler,looper和messagequeue的关系。
4:我们继续跟踪在AsyncQueryHandler中startQuery的流程,发送查询事件消息。 由mWorkerThreadHandler的handleMessage()来执行resolver.Query()操作。并将查询结果以消息的形式转发给this.
5:由AsyncQueryHandler的handleMessage()来调用onQueryComplete()函数,这个函数在ThreadListQueryHandler被重写。
6:在ConversationList的ThreadListQueryHandler中实现了onQueryComplete()函数,这里我们根据处理结果,mListAdapter.changeCursor(),来更新界面,如果cursor.getCount()=0, 就显示无会话。
handler的继承关系和说明
1:ThreadListQueryHandler是ConversationList中的内部类,在onCreate中初始化,用于异步加载数据
2,根据上图我们可以看出 ThreadListQueryHandler的层级继承关系,而这里最重要的就是AsyncQueryHandler, 这个类新建了一个thread,用新建thread的looper构建一个mWorkerThreadHandler, 在这个handler中的handleMessage里进行resolver.Query()的操作,并且将得到的cursor,传递到了基于主UI线程的AsyncQueryHandler自身的handleMessage中来使用。
PS:特别注意里面两个handleMessage的关系,主UI线程和新建thread的消息传递
解析Uri 和 查询的 参数
1: Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build()是Uri的赋值
2:通过在/msm8916/frameworks/opt/telephony/src/java/android/provider/Telephony.java中查询得出content://mms-sms/conversations
3:在MmsSmsProvider中query的case是URI_CONVERSATIONS。同时传递参数为String simple = uri.getQueryParameter("simple"),所以进行getSimpleConversations查询
4:mOpenHelper.getReadableDatabase().query(TABLE_THREADS, projection,selection, selectionArgs, null, null, " date DESC"),这里得出是在threads表中查询
[edit]Data加载到ConversationList的过程
1:在ConversationListAdapter中调用bindView
public void bindView(View view, Context context, Cursor cursor) { if (!(view instanceof ConversationListItem)) { Log.e(TAG, "Unexpected bound view: " + view); return; }
ConversationListItem headerView = (ConversationListItem) view; Conversation conv = Conversation.from(context, cursor); headerView.bind(context, conv); }
2:在conversation中调用from函数得到一个conversation,其中涉及到缓存
public static Conversation from(Context context, Cursor cursor) { // First look in the cache for the Conversation and return that one. That way, all the // people that are looking at the cached copy will get updated when fillFromCursor() is // called with this cursor. long threadId = cursor.getLong(ID); if (threadId > 0) { Conversation conv = Cache.get(threadId); if (conv != null) { fillFromCursor(context, conv, cursor, false); // update the existing conv in-place return conv; } } Conversation conv = new Conversation(context, cursor, false); try { Cache.put(conv); } catch (IllegalStateException e) { LogTag.error(TAG, "Tried to add duplicate Conversation to Cache (from cursor): " + conv); if (!Cache.replace(conv)) { LogTag.error("Converations.from cache.replace failed on " + conv); } } return conv; 对已经在缓存中的数据,直接拿出来用,没有的对cache进行填充
3:其中cache初始化个HashSet 10个空间的样子
private static Cache sInstance = new Cache(); static Cache getInstance() { return sInstance; } private final HashSet<Conversation> mCache; private Cache() { mCache = new HashSet<Conversation>(10); }
超过10个cache进行 add 操作。
4:得到conversation后到ConversationListItem中的bind函数中 对listview的控件赋值。
更多推荐
高通Android 4.4 短信应用ConversationList 的分析
发布评论