DialpadFragment.java afterTextChanged() 方法:
if (mDialpadQueryListener != null) {
mDialpadQueryListener.onDialpadQueryChanged(mDigits.getText().toString());
}
在onResume()中:
final DialtactsActivity activity = (DialtactsActivity) getActivity();
mDialpadQueryListener = activity;
DialtactsActivity.java
onDialpadQueryChanged()方法中 主要就是EditText设置搜索内容
mSearchView.setText(normalizedQuery);
然后走mSearchView的onTextChanged
if (mSmartDialSearchFragment != null && mSmartDialSearchFragment.isVisible()) {
//如果是在拨号盘搜索,走这里
mSmartDialSearchFragment.setQueryString(mSearchQuery);
} else if (mRegularSearchFragment != null && mRegularSearchFragment.isVisible()) {
//如果是搜索联系人,走这里
mRegularSearchFragment.setQueryString(mSearchQuery);
} else if (mNewSearchFragment != null) {
//这里暂时还没找
mNewSearchFragment.setQuery(mSearchQuery);
}
3.SmartDialSearchFragment.java 他继承于 ContactEntryListFragment.java
先看ContactEntryListFragment走了setQueryString()方法
public void setQueryString(String queryString) {
if (!TextUtils.equals(mQueryString, queryString)) {
if (mShowEmptyListForEmptyQuery && mAdapter != null && mListView != null) {
if (TextUtils.isEmpty(mQueryString)) {
// Restore the adapter if the query used to be empty.
mListView.setAdapter(mAdapter);
} else if (TextUtils.isEmpty(queryString)) {
// Instantly clear the list view if the new query is empty.
mListView.setAdapter(null);
}
}
mQueryString = queryString;
setSearchMode(!TextUtils.isEmpty(mQueryString) || mShowEmptyListForEmptyQuery);
if (mAdapter != null) {
mAdapter.setQueryString(queryString);
//走了这里进行数据加载
reloadData();
}
}
}
reloadData 主要是startLoading()方法开始进行数据加载
protected void reloadData() {
removePendingDirectorySearchRequests();
mAdapter.onDataReload();
mLoadPriorityDirectoriesOnly = true;
mForceLoad = true;
startLoading();
}
startLoading()方法
protected void startLoading() {
if (mAdapter == null) {
// The method was called before the fragment was started
return;
}
configureAdapter();
int partitionCount = mAdapter.getPartitionCount();
for (int i = 0; i < partitionCount; i++) {
Partition partition = mAdapter.getPartition(i);
if (partition instanceof DirectoryPartition) {
DirectoryPartition directoryPartition = (DirectoryPartition) partition;
if (directoryPartition.getStatus() == DirectoryPartition.STATUS_NOT_LOADED) {
if (directoryPartition.isPriorityDirectory() || !mLoadPriorityDirectoriesOnly) {
startLoadingDirectoryPartition(i);
}
}
} else {
//初始化Loader
getLoaderManager().initLoader(i, null, this);
}
}
然后我们看LoaderManager.java 中initLoader方法
LoaderManager是个抽象类,他里面LoaderManagerImpl继承了Loadermanager我们看LoaderManagerImpl找那个的initLoader方法
public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}
LoaderInfo info = mLoaders.get(id);
if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);
if (info == null) {
// Loader doesn't already exist; create.
//创建LoaderInfor
info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
if (DEBUG) Log.v(TAG, " Created new loader " + info);
} else {
if (DEBUG) Log.v(TAG, " Re-using existing loader " + info);
info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
}
if (info.mHaveData && mStarted) {
// If the loader has already generated its data, report it now.
info.callOnLoadFinished(info.mLoader, info.mData);
}
//将Loader返回
return (Loader<D>)info.mLoader;
}
我们看createAndInstallLoader()方法里面:
private LoaderInfo createAndInstallLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
try {
mCreatingLoader = true;
//创建Loader();
LoaderInfo info = createLoader(id, args, callback);
//执行loader.start()方法
installLoader(info);
return info;
} finally {
mCreatingLoader = false;
}
}
private LoaderInfo createLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
LoaderInfo info = new LoaderInfo(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
//onCreateLoader方法在SmartDialSearchFragment.java文件中
Loader<Object> loader = callback.onCreateLoader(id, args);
info.mLoader = (Loader<Object>)loader;
return info;
}
我们看SmartDialSearchFragment.java文件中的onCreateLoader方法
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// Smart dialing does not support Directory Load, falls back to normal search instead.
if (id == getDirectoryLoaderId()) {
return super.onCreateLoader(id, args);
} else {
final SmartDialNumberListAdapter adapter = (SmartDialNumberListAdapter) getAdapter();
/// M: [MTK Dialer Search] @{
if (DialerFeatureOptions.isDialerSearchEnabled()) {
DialerSearchCursorLoader loader = new DialerSearchCursorLoader(super.getContext(), id,
getLoaderManager());
adapter.configureLoader(loader);
return loader;
/// @}
} else {
//创建SmartDialCursorLoader并返回
SmartDialCursorLoader loader = new SmartDialCursorLoader(super.getContext());
loader.setShowEmptyListForNullQuery(getShowEmptyListForNullQuery());
adapter.configureLoader(loader);
return loader;
}
}
}
我们回到LoaderManager.java 中继续看installLoader()方法
void installLoader(LoaderInfo info) {
mLoaders.put(info.mId, info);
if (mStarted) {
// The activity will start all existing loaders in it's onStart(),
// so only start them here if we're past that point of the activitiy's
// life cycle
//调用了start()方法 在start()方法中执行了mLoader.startLoading();
info.start();
}
}
我们看mLoader.startLoading(),mLoader是我们刚刚在SmartDialSearchFragment.java类中创建的SmartDialCursorLoader对象
@Override
protected void onStartLoading() {
if (mCursor != null) {
/** Deliver any previously loaded data immediately. */
deliverResult(mCursor);
}
if (mCursor == null) {
/** Force loads every time as our results change with queries. */
//forceLoad调用 Loader.java中的onForceLoad()方法
forceLoad();
}
}
我们来看onForceLoad()方法,因为SmartDialCursorLoader继承AsyncTaskLoader,在AsyncTaskLoader中看onForceLoad()方法
@Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();//创建AsyncTask病执行
if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);
executePendingTask();//执行AsyncTask
}
接下来看执行耗时操作
protected D doInBackground(Void... params) {
if (DEBUG) Log.v(TAG, this + " >>> doInBackground");
try {
//调用了onLoadInBackground()中会调用loadInBackground()方法,loadInBackground()方法SmartDialCursorLoader重写了
D data = AsyncTaskLoader.this.onLoadInBackground();
if (DEBUG) Log.v(TAG, this + " <<< doInBackground");
return data;
} catch (OperationCanceledException ex) {
if (!isCancelled()) {
// onLoadInBackground threw a canceled exception spuriously.
// This is problematic because it means that the LoaderManager did not
// cancel the Loader itself and still expects to receive a result.
// Additionally, the Loader's own state will not have been updated to
// reflect the fact that the task was being canceled.
// So we treat this case as an unhandled exception.
throw ex;
}
if (DEBUG) Log.v(TAG, this + " <<< doInBackground (was canceled)", ex);
return null;
}
}
我们来看SmartDialCursorLoader.java中的loadInBackground方法
public Cursor loadInBackground() {
if (DEBUG) {
LogUtil.v(TAG, "Load in background " + mQuery);
}
if (!PermissionsUtil.hasContactsReadPermissions(mContext)) {
return new MatrixCursor(PhoneQuery.PROJECTION_PRIMARY);
}
/** Loads results from the database helper. */
final DialerDatabaseHelper dialerDatabaseHelper =
Database.get(mContext).getDatabaseHelper(mContext);
final ArrayList<ContactNumber> allMatches =
dialerDatabaseHelper.getLooseMatches(mQuery, mNameMatcher);//这里做数据库的查询操作
if (DEBUG) {
LogUtil.v(TAG, "Loaded matches " + allMatches.size());
}
//将查询到的数据插入新表中并返回游标
final MatrixCursor cursor = new MatrixCursor(PhoneQuery.PROJECTION_PRIMARY);
Object[] row = new Object[PhoneQuery.PROJECTION_PRIMARY.length];
for (ContactNumber contact : allMatches) {
row[PhoneQuery.PHONE_ID] = contact.dataId;
row[PhoneQuery.PHONE_NUMBER] = contact.phoneNumber;
row[PhoneQuery.CONTACT_ID] = contact.id;
row[PhoneQuery.LOOKUP_KEY] = contact.lookupKey;
row[PhoneQuery.PHOTO_ID] = contact.photoId;
row[PhoneQuery.DISPLAY_NAME] = contact.displayName;
row[PhoneQuery.CARRIER_PRESENCE] = contact.carrierPresence;
cursor.addRow(row);
}
return cursor;
}
这时耗时操作执行完毕,我们继续来看AsyncTaskLoader 中onPostExecute方法
他执行了 AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
void dispatchOnLoadComplete(LoadTask task, D data) {
if (mTask != task) {
if (DEBUG) Log.v(TAG, "Load complete of old task, trying to cancel");
dispatchOnCancelled(task, data);
} else {
if (isAbandoned()) {
// This cursor has been abandoned; just cancel the new data.
onCanceled(data);
} else {
commitContentChanged();
mLastLoadCompleteTime = SystemClock.uptimeMillis();
mTask = null;
if (DEBUG) Log.v(TAG, "Delivering result");
//将搜索的数据通过接口返回
deliverResult(data);
}
}
}
public void deliverResult(D data) {
mListener是来自LoaderManager方法中
if (mListener != null) {
mListener.onLoadComplete(this, data);
}
}
我们来看LoaderManager方法中的
@Override
public void onLoadComplete(Loader<Object> loader, Object data) {
//主要代码
if (mData != data || !mHaveData) {
mData = data;
mHaveData = true;
if (mStarted) {
//调用的callOnLoadFinished()将数据放回
callOnLoadFinished(loader, data);
}
}
}
void callOnLoadFinished(Loader<Object> loader, Object data) {
if (mCallbacks != null) {
String lastBecause = null;
if (mHost != null) {
lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished";
}
try {
if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": "
+ loader.dataToString(data));
//mCallback是来自ContactEntryListFragment类实现了该方法
mCallbacks.onLoadFinished(loader, data);
} finally {
if (mHost != null) {
mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
}
}
mDeliveredData = true;
}
}
我们看ContactEntryListFragment.java中的onLoadFinished()方法
他的主要方法
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//onPartitionLoader方法将数据传给Adapter并刷新数据
onPartitionLoaded(loaderId, data);
if (isSearchMode()) {
int directorySearchMode = getDirectorySearchMode();
if (directorySearchMode != DirectoryListLoader.SEARCH_MODE_NONE) {
if (mDirectoryListStatus == STATUS_NOT_LOADED) {
mDirectoryListStatus = STATUS_LOADING;
getLoaderManager().initLoader(DIRECTORY_LOADER_ID, null, this);
} else {
startLoading();
}
}
} else {
mDirectoryListStatus = STATUS_NOT_LOADED;
getLoaderManager().destroyLoader(DIRECTORY_LOADER_ID);
}
}
protected void onPartitionLoaded(int partitionIndex, Cursor data) {
if (partitionIndex >= mAdapter.getPartitionCount()) {
// When we get unsolicited data, ignore it. This could happen
// when we are switching from search mode to the default mode.
return;
}
// Return for non-"Suggestions" if on the zero-suggest screen.
if (TextUtils.isEmpty(mQueryString) && partitionIndex > 0) {
return;
}
//调用changeCursor进行刷新数据
mAdapter.changeCursor(partitionIndex, data);
setProfileHeader();
if (!isLoading()) {
completeRestoreInstanceState();
}
}