android系统自带短信程序源码部分分析_第1页
android系统自带短信程序源码部分分析_第2页
android系统自带短信程序源码部分分析_第3页
android系统自带短信程序源码部分分析_第4页
android系统自带短信程序源码部分分析_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、系统自带短信程序源码部分分析文章分类:移动开发这里并不打算对整个短信源码进行分析,完全是看了某部分代码后的自我总结。我从GIT上clone 了 Conversation (即短信程序)的所有源码,结果编译不过。 不过这对分析它的源码并不造成太大的阻碍。这里主要对短信主界面的数据和 UI的交互角度进行分析,因为我自己写的短信 程序在加入获取联系人头像功能后,程序启动时花费的查询时间太长。虽然我也 觉得系统默认的短信程序,甚至 HandcentSMS启动时间都不是很快。(大概是 我的机器性能太差)一、代码结构Conversation 中整体结构主要包括 com.android.mms.data 和

2、com.android.mms.ui,如名字所示,大概就是数据处理部分和UI部分。数据部分主要是获取/缓存联系人信息、获取/缓存会话信息等。ConversationList 类是程序的主activity ,派生于ListActivity ,就是一个大 的列表。此外:ConversationListAdapter 是这个 ListView 的 adapter,派生于 CursorAdapter ; ConversationListItem 是一个自定义的 ViewGroup,派生于 RelativeLayout , 用于表示会话列表的每一个itemConversation表示一个会话数据;Con

3、tact表示一个联系人;ContactList 维护 一个联系人列表;RecipientIdCache用于开线程读取一个特殊的表,该表映射会话数据到联系人 信息,也就是通过Recipient就可以获取联系人信息。二、UI结构这里的UI主要就是ConversationList/ConversationListAdapter/ConversationListItem三者之间的交互。在 layout 中,conversation_list_item.xml作为这个 ListView(ConversationList )的 item 定义,直接使用了 ConversationListItem 这个 v

4、iew :Java代码1. 这个自定义item最重要的工作,就是将会话数据绑定到 UI控件上,例如QuickContactBadge。在ListView 的使用中,要绑定数据,还有个方法就是自写 adapter ,在构造adapter时就传入所有数据。但是如你所见,这种方法需要先 读取出所有的数据。而这个系统自带的短信程序,则没有一次读入。这个自定义 item还有个功能就 是,作为一条联系人信息的更新监听器。 读取联系人信息是非常慢的,因为会涉 及到几个表的查询。在构造这个item时,程序在另一个线程中异步读取联系人 信息,而item只有一个联系人的简要信息(电话号码)。当联系人读出来后, 再

5、通知它的监听器,也就是这个item ,然后更新UI显示。ConversationListAdapter中只实现了 bindView 和 newView这两个函数,此外,它作为 listView 的 AbsListView.RecyclerListener ,还实现了 onMovedToScrapHeap 数。关于RecyclerListener ,这里有篇文章从源码级角度分析了下,大概意思就是ListView 在处理item时,有个缓存机制。三、数据与UI的映射 这部分才是重要的分析部分,也是我需要学习的部分。ConversationList 的onStart中,开启了一个异步查询,查询所有的

6、会话:Java代码 -1. Override2. protected void onStart() 3. super.onStart();4.5. .6. startAsyncQuery();startyAsyncQuery 调用了 Conversation.startQueryForAll 函数,该函数说白 了还是调用 AsyncQueryHandler.startQuery 函数:Java代码1. public static void startQueryForAll(AsyncQueryHandler handl er, int token) 2. handler.cancelOpera

7、tion(token);3. handler.startQuery(token, null,sAllThreadsUri,4. ALL_THREADS_PROJECTIONull, null,Conversations.DEFAULT_SORT_ORDER);5. 关于如何获取会话列表,其实就是个SQL的连表查询,可以参见这里:获取短信 会话列表当查询完后,android 回调到自己实现的 AsyncQueryHandler.onQueryComplete , 该函数主要就是告诉 adapter , we have done!:Java代码1. Override2. protected voi

8、d onQueryComplete(int token, Object cookie, Cursor cursor) 3. switch (token) 4. case THREAD_LIST_QUERY_TOKEN:5. mListAdapter.changeCursor(cursor);一旦adapter获得了一个cursor后,就会主动去取得listview 的各项数据。以 上便是获取会话列表的大致流程。接下来看看联系人获取的流程:adapter获得数据后,会调用bindView来绑定数据到UI的item :Java代码 -1. Override2. public void bindVi

9、ew(View view, Context context, Cursor cursor) 3. if (!(view instanceof ConversationListItem) 4. Log.e(TAG, Unexpected bound view: + view); 5.return;6. 7.8. ConversationListItem headerView = (ConversationListItem) view;9. Conversation conv = Conversation.from(context, cursor);10.11. ConversationListI

10、temDatach = new ConversationListItemData(context, conv);12. headerView.bind(context,ch);13. Conversation.from函数会先检查 Conversation 缓存中是否有该 cursor对应的数据,没有的话则会从cursor中取:Java代码1. public static Conversation from(Context context, Cursor c ursor) 2. / First look in the cache for the Conversationand return t

11、hat one. That way, all the3. / people that are looking at the cached copywill get updated when fillFromCursor() is4. / called with this cursor.5. long threadId= cursor.getLong(ID);6. if (threadId 0) 7. Conversationconv = Cache.get(threadId);8. if (conv !=null) 9. f川FromCursor(context,conv, cursor,fa

12、lse);/ update the existing conv in-place10. return conv;11. 12. 13. Conversationconv = new Conversation(context, cursor, false);14. try 15. Cache.put(conv);16. catch(IllegalStateException e) 17. LogTag.error(Triedto add duplicate Conversationto Cache);18. 19. return conv;20. 然后主要是fillFromCursor 函数(如

13、果是创建新的Conversation ,其构造函数 中也是调用了该函数),该函数就是简单地从cursor中getXXXX获取各个数据, 并且,最重要的,获取联系人信息:Java代码1. privateConversation2.3.4. .5.s(recipientIds,static void fillFromCursor(Context context, conv,Cursor c, boolean allowQuery) ContactList recipients = ContactList.getById allowQuery);注意这里allowQuery参数为false 。Con

14、tactList.getByIds 函数根据 Conversation 中 recipientIds 获取出对应的 address ,然后根据address从联系人URI中进一步获取联系人信息。Java代码1. public static ContactList getByIds(String spaceSepIds, boo lean canBlock) 2. ContactList list = new ContactList();3. for (RecipientIdCache.Entry entry : RecipientIdCache.getAddresses(spaceSepIds

15、) 4. if (entry != null & !TextUtils.isEmpty(entry.number) 5. Contact contact = Contact.get(entry.number, canBlock);6. contact.setRecipientId(entry.id);7. list.add(contact);8. 9. 10. returnlist;11. 最终的 contact 被生成于 Contact.get(entry.number, canBlock)中。该函数在canBlock为false的情况下,会push 一个异步执行体(Runnable)到一个

16、线程中。 然后将contact返回。最终返回到adapter那一层的函数。这个异步查询线程,会真正地去查询联系人信息。在此之前,外界获取出来的联 系人不过是一个很简单的信息:只有电话号码。adapter 的 bindView 中,紧接着:Java代码ch = new ConversationListI ch);1. ConversationListItemDatatemData(context, conv);2. headerView.bind(context,3. bind函数中很重要的操作,就是建立该会话对应的联系人对象的监听:Java代码1. ContactList contacts =

17、 ch.getContacts();2.3. if (DEBUG) Log.v(TAG, bind: contacts.addListeners + t his);4. Contact.addListener(this);以上过程,即展示了会话数据是如何映射到ListView的item ,及联系人信息是如何与会话和listview item建立联系(即异步查询,然后同步)。值得一提的是:查询联系人信息都是在bindView时发生,当一个listview 被显 示出来后,未显示的item是不会被触发bind的,也就是说:在listview 显示 时,不会触发查询整个会话对应的所有联系人,只有显示出来的 item才会涉及 到查询联系人。基于以上,我写了一个测试程序。结果似乎很好,就像系统自带的短信程序一样。 启动速度依然不算快。问题的所在,似乎并不在于查询时间花费的很长。listview 倒是早就显示出来了(看见了程序标题),但是 i

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论