1.2 查询通话记录
CallLogFragment的fetchCalls调用流程图如下,
fetchCalls方法如下,
public void fetchCalls() {
mCallLogQueryHandler.fetchCalls(mCallTypeFilter, mDateLimit);
}
CallLogQueryHandler有不同参数的fetchCalls方法,最后的fetchCalls方法主要逻辑如下,
1,构造查询语句,
StringBuilder where = new StringBuilder();
List<String> selectionArgs = Lists.newArrayList();
// Ignore voicemails marked as deleted
where.append(Voicemails.DELETED);
where.append(" = 0");
if (newOnly) {
where.append(" AND ");
where.append(Calls.NEW);
where.append(" = 1");
}
•••
2,根据通话记录查询类型构造查询参数,
if (callType > CALL_TYPE_ALL) {
if (where.length() > 0) {
where.append(" AND ");
}
if ((callType == Calls.INCOMING_TYPE) || (callType == Calls.OUTGOING_TYPE)
|| (callType == Calls.MISSED_TYPE)) {
where.append(String.format("(%s = ? OR %s = ?)",
Calls.TYPE, Calls.TYPE));
} else {
// Add a clause to fetch only items of type voicemail.
where.append(String.format("(%s = ?)", Calls.TYPE));
}
// Add a clause to fetch only items newer than the requested date
selectionArgs.add(Integer.toString(callType));
if (callType == Calls.INCOMING_TYPE) {
selectionArgs.add(Integer.toString(INCOMING_IMS_TYPE));
} else if (callType == Calls.OUTGOING_TYPE) {
selectionArgs.add(Integer.toString(OUTGOING_IMS_TYPE));
} else if (callType == Calls.MISSED_TYPE) {
selectionArgs.add(Integer.toString(MISSED_IMS_TYPE));
}
•••
3,获取URI
final int limit = (mLogLimit == -1) ? NUM_LOGS_TO_DISPLAY : mLogLimit;
final String selection = where.length() > 0 ? where.toString() : null;
Uri uri = TelecomUtil.getCallLogUri(mContext).buildUpon()
.appendQueryParameter(Calls.LIMIT_PARAM_KEY, Integer.toString(limit)).build();
4,调用startQuery方法进行查询,
startQuery(token, null, uri, CallLogQuery._PROJECTION, selection,
selectionArgs.toArray(EMPTY_STRING_ARRAY), Calls.DEFAULT_SORT_ORDER);
父类NoNullCursorAsyncQueryHandler的startQuery方法如下,
public void startQuery(int token, Object cookie, Uri uri, String[] projection, String selection,
String[] selectionArgs, String orderBy) {
final CookieWithProjection projectionCookie = new CookieWithProjection(cookie, projection);
super.startQuery(token, projectionCookie, uri, projection, selection, selectionArgs, orderBy);
}
直接调用父类AsyncQueryHandler的startQuery方法进行异步查询, AsyncQueryHandler的原理在此不论述了。只需要知道的是AsyncQueryHandler查询完成之后会回调onQueryComplete方法。
NoNullCursorAsyncQueryHandler的onQueryComplete方法如下,
protected final void onQueryComplete(int token, Object cookie, Cursor cursor) {
CookieWithProjection projectionCookie = (CookieWithProjection) cookie;
super.onQueryComplete(token, projectionCookie.originalCookie, cursor);
if (cursor == null) {
cursor = new EmptyCursor(projectionCookie.projection);
}
onNotNullableQueryComplete(token, projectionCookie.originalCookie, cursor);
}
onNotNullableQueryComplete方法是一个abstract方法,子类CallLogQueryHandler的实现如下,
if (token == QUERY_CALLLOG_TOKEN) {
if (updateAdapterData(cursor)) {
cursor = null;
}
•••
如果是普通的通话记录,就调用updateAdapterData方法更新数据。
updateAdapterData方法如下,
private boolean updateAdapterData(Cursor cursor) {
final Listener listener = mListener.get();
if (listener != null) {
return listener.onCallsFetched(cursor);
}
return false;
}
回调监听器的onCallsFetched方法。
因此,查询完成之后,会调用各个Fragment的onCallsFetched方法。