在短信会话列表界面,点击其中一条记录,会进入相对应的短信会话详情界面。
短信加载内容分为草稿和历史聊天记录。UI分面分为新建短信和打开已经保存在数据库的历史短信会话。
新建短信在前面我们已经分析了。现在我们来分析打开已经保存在数据库的历史短信会话的流程。并且分析短信加载草稿和历史聊天记录的流程。
ConversationList.java
public void openThread(long threadId) {//打开threadId对应的会话
startActivity(ComposeMessageActivity.createIntent(this, threadId));
}
其中有很多是跟新建短信一样的,我们着重分析不一样和前面没有分析过的代码流程。
onCreate
initialize
initActivityState
long threadId = intent.getLongExtra(THREAD_ID, 0);
if (threadId > 0) {
if (LogTag.VERBOSE) log("get mConversation by threadId " + threadId);
mConversation = Conversation.get(this, threadId, false);
}
Conversation 可以说是一个会话的上下文,WorkingMessage表示正在编辑的相关内容,而Conversation对应thread表的内容
get会去缓存查找,我们第一次进入是null,所以需要新建
private Conversation(Context context, long threadId, boolean allowQuery) {//此时allowQuery传递进来的是false
if (DEBUG) {
Log.v(TAG, "Conversation constructor threadId: " + threadId);
}
mContext = context;
if (!loadFromThreadId(threadId, allowQuery)) {
mRecipients = new ContactList();
mThreadId = 0;
}
}
loadFromThreadId(threadId, allowQuery)
Cursor c = mContext.getContentResolver().query(sAllThreadsUri, ALL_THREADS_PROJECTION,
"_id=" + Long.toString(threadId), null, null);根据threadId查找thread表
fillFromCursor(mContext, this, c, allowQuery);根据查询到的内容填充Conversation
这部分读者自己查看,就是查询到的内容填充Conversation的变量
ContactList recipients = ContactList.getByIds(recipientIds, allowQuery);
recipientIds这个是收件人id,查询具体的联系人详情,这个后面说
else {
hideRecipientEditor();
}//不需要收件人编辑框,隐藏之。
drawBottomPanel();//需要绘制文字编辑框相关的区域
接下来是onStart的查询历史记录内容和加载草稿
loadMessagesAndDraft(2);
loadMessageContent();加载短信内容
startMsgListQuery();
startMsgListQuery(MESSAGE_LIST_QUERY_TOKEN);
mBackgroundQueryHandler.startQuery(
token,
threadId /* cookie */,
conversationUri,
PROJECTION,
null, null, null);
具体到数据库,会查询thread_Id为threadId的文字短信和彩信返回。
查询结束后,会回调BackgroundQueryHandler的onQueryComplete
mMsgListAdapter.changeCursor(cursor);改变list的内容
接下来还会加载草稿
loadDraft()
mWorkingMessage = WorkingMessage.loadDraft(this, mConversation,
new Runnable() {
@Override
public void run() {
updateMmsSizeIndicator();
// It decides whether or not to display the subject editText view,
// according to the situation whether there's subject
// or the editText view is visible before leaving it.
drawTopPanel(isSubjectEditorVisible());
drawBottomPanel();
updateSendButtonState();
}
});
WorkingMessage.java
loadDraft
final WorkingMessage msg = createEmpty(activity);
if (conv.getThreadId() <= 0) {//threadId为空,直接执行回调,刷新UI
if (onDraftLoaded != null) {
onDraftLoaded.run();
}
return msg;
}
new AsyncTask<Void, Void, Pair<String, String>>() {开启后台线程查询草稿
protected Pair<String, String> doInBackground(Void... none) {
// Look for an SMS draft first.
String draftText = msg.readDraftSmsMessage(conv);//查询文本短信的草稿
String subject = null;
if (TextUtils.isEmpty(draftText)) {
// No SMS draft so look for an MMS draft.
StringBuilder sb = new StringBuilder();
Uri uri = readDraftMmsMessage(msg.mActivity, conv, sb);//如果没有文本短信草稿,则查询彩信草稿
if (uri != null) {
if (msg.loadFromUri(uri)) {//如果pdu表有记录,则继续加载part表中彩信内容
// If there was an MMS message, readDraftMmsMessage
// will put the subject in our supplied StringBuilder.
subject = sb.toString();
}
}
}
Pair<String, String> result = new Pair<String, String>(draftText, subject);
return result;
}
readDraftSmsMessage
Cursor c = SqliteWrapper.query(mActivity, mContentResolver,
thread_uri, SMS_BODY_PROJECTION, SMS_DRAFT_WHERE, null, null);
查询类型为draft的thread_id为threadId的sms表的记录,此时只需要Sms.BODY这个字段的内容
如果查询到了有文本草稿,则asyncDeleteDraftSmsMessage(conv);删除掉文本草稿,因为已经加载成功了,而且草稿有可能继续编辑,所以原来的那个已经无用了。
readDraftMmsMessage
cursor = SqliteWrapper.query(context, cr,
Mms.Draft.CONTENT_URI, MMS_DRAFT_PROJECTION,
selection, null, null);
这个只是查找了pdu表的,如果有彩信草稿,我们还需要加载part表,将彩信内容加载出来。
loadFromUri
mSlideshow = SlideshowModel.createFromMessageUri(mActivity, uri);我们之前说过,彩信内容就是存放在SlideshowModel中的。
这样加载完内容后就回调刷新UI。