短信界面更新
1、核心类
MessageListview
MessageListAdapter
MmsProvider
MmsSmsProvider
SmsProvider
2、provider的分类
数据库的概况
这是短信数据库的大致情况,对于短信而言最重要的表就是sms threads words
2.1 Smsprovider
uri:content://sms
该provider是针对sms表进行的增 删 改 查
2.2 MmsProvider
uri: content://mms
负责part、pdu表的增 删 改 查
2.3 MmsSmsProvider
content://mms-sms/
主要负责threads的表的增 删 改 查;
且这个provider 是短信和彩信共有的,且与主界面更新相关
注意:同时对sms、mms都有相应的操作
3、具体实现
3.1 数据库监听
1)监听数据库改变
mMsgListAdapter = new MessageListAdapter(this,null,mMsgListView,true, highlight);
mMsgListAdapter.setOnDataSetChangedListener(mDataSetChangedListener);
mMsgListAdapter.setMsgListItemHandler(mMessageListItemHandler);
mMsgListView.setAdapter(mMsgListAdapter);
2)主动更新,当privider内容改变的时候
private final MessageListAdapter.OnDataSetChangedListener
mDataSetChangedListener =new MessageListAdapter.OnDataSetChangedListener() {
public void onDataSetChanged(MessageListAdapter adapter) {
mPossiblePendingNotification =true;
}
public void onContentChanged(MessageListAdapter adapter) {
startMsgListQuery();
}
};
3)查询该方法:
private void startMsgListQuery() {
Uri conversationUri = mConversation.getUri();
if (conversationUri ==null) {
return;
}
if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
log("for " + conversationUri);
}
// Cancel any pending queries
mBackgroundQueryHandler.cancelOperation(MESSAGE_LIST_QUERY_TOKEN);
try {
// Kick off the new query
mBackgroundQueryHandler.startQuery(
MESSAGE_LIST_QUERY_TOKEN,null, conversationUri,
PROJECTION,null,null,null);
} catch (SQLiteException e) {
SqliteWrapper.checkSQLiteException(this, e);
}
}
这里的uri是:content://mms-sms/conversations/2
3.2 provider的实现
1)由于这里是界面的更新所以使用的是MmsSmsProvider,且看其查询短信的实现:
case URI_CONVERSATIONS_MESSAGES:
cursor = getConversationMessages(
uri.getPathSegments().get(1), projection, selection,
selectionArgs, sortOrder);
break;
2)然后查看对应方法:
private CursorgetConversationMessages(
String threadIdString, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
try {
Long.parseLong(threadIdString);
} catch (NumberFormatException exception) {
Log.e(LOG_TAG,"Thread ID must be a Long.");
return null;
}
String finalSelection = concatSelections(
selection, "thread_id = " + threadIdString);
String unionQuery = buildConversationQuery(
projection, finalSelection, selectionArgs, sortOrder);
returnmOpenHelper.getReadableDatabase().rawQuery(unionQuery,EMPTY_STRING_ARRAY);
}
3)对于红色部分特别标示是因为,这里时区查询对应的数据库信息。请看下面是其核心代码:
private static String buildConversationQuery(String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
String[] mmsProjection = createMmsProjection(projection);
SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
SQLiteQueryBuilder smsQueryBuilder = new SQLiteQueryBuilder();
mmsQueryBuilder.setDistinct(true);
smsQueryBuilder.setDistinct(true);
mmsQueryBuilder.setTables(joinPduAndPendingMsgTables());
smsQueryBuilder.setTables(SmsProvider.TABLE_SMS);
String[] smsColumns = handleNullMessageProjection(projection);
String[] mmsColumns = handleNullMessageProjection(mmsProjection);
String[] innerMmsProjection = makeProjectionWithNormalizedDate(mmsColumns, 1000);
String[] innerSmsProjection = makeProjectionWithNormalizedDate(smsColumns, 1);
Set<String> columnsPresentInTable = new HashSet<String>(MMS_COLUMNS);
columnsPresentInTable.add("pdu._id");
columnsPresentInTable.add(PendingMessages.ERROR_TYPE);
String mmsSelection = concatSelections(selection,
Mms.MESSAGE_BOX +" != " + Mms.MESSAGE_BOX_DRAFTS);
String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(
MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerMmsProjection,
columnsPresentInTable, 0, "mms",
concatSelections(mmsSelection, MMS_CONVERSATION_CONSTRAINT),
selectionArgs, null,null);
String smsSubQuery = smsQueryBuilder.buildUnionSubQuery(
MmsSms.TYPE_DISCRIMINATOR_COLUMN, innerSmsProjection,SMS_COLUMNS,
0, "sms", concatSelections(selection, SMS_CONVERSATION_CONSTRAINT),
selectionArgs, null,null);
SQLiteQueryBuilder unionQueryBuilder = new SQLiteQueryBuilder();
unionQueryBuilder.setDistinct(true);
String unionQuery = unionQueryBuilder.buildUnionQuery(
new String[] { smsSubQuery, mmsSubQuery },
handleNullSortOrder(sortOrder), null);
SQLiteQueryBuilder outerQueryBuilder = new SQLiteQueryBuilder();
outerQueryBuilder.setTables("(" + unionQuery +")");
return outerQueryBuilder.buildQuery(
smsColumns, null,null,null,null, sortOrder,null);
这里是构建一个复合查询类似于:select *from sms,mms;即是会去查询出当前会话所有的彩信和短信,然后显示,所以这里的话一旦sms和mms provider的内容发生变化都会触发更新界面,这里一般是在发送和接收时会触发。4、sms表设计技巧
在sms表设计的时候有给该表创建一些触发器;
// Updates threads table whenever a message is added to sms.
db.execSQL("CREATE TRIGGER sms_update_thread_on_insert AFTER INSERT ON sms " +
SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
// Updates threads table whenever a message in sms is updated.
db.execSQL("CREATE TRIGGER sms_update_thread_date_subject_on_update AFTER" +
" UPDATE OF " + Sms.DATE + ", " + Sms.BODY + ", " + Sms.TYPE +
" ON sms " +
SMS_UPDATE_THREAD_DATE_SNIPPET_COUNT_ON_UPDATE);
// Updates threads table whenever a message in sms is updated.
db.execSQL("CREATE TRIGGER sms_update_thread_read_on_update AFTER" +
" UPDATE OF " + Sms.READ +
" ON sms " +
"BEGIN " +
SMS_UPDATE_THREAD_READ_BODY +
"END;");
db.execSQL("CREATE TRIGGER delete_obsolete_threads_when_update_pdu " +
"AFTER UPDATE OF " + Mms.THREAD_ID + " ON pdu " +
"WHEN old." + Mms.THREAD_ID + " != new." + Mms.THREAD_ID + " " +
"BEGIN " +
" DELETE FROM threads " +
" WHERE " +
" _id = old.thread_id " +
" AND _id NOT IN " +
" (SELECT thread_id FROM sms " +
" UNION SELECT thread_id from pdu); " +
"END;");
大家可以看到当更新sms表或者其他动作时就会触发去更新4、总结
该文主要是针对界面更新展开来描述的,其数据库的作用远远不止于此。