Android 8.1电话拨号盘搜索源码逻辑分析

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();
    }
  }

    

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值