Android Q SettingsIntelligence ---- Settings搜索框

丌官博文
2023-12-01

                   基于Android Q的SettingsIntelligence源码

  1. 使用命令adb logcat|grep "cmp",点击Settings下的搜索框,我们得到如下输出:

04-17 13:38:13.690  1030  1451 I ActivityTaskManager: START u0 {act=android.settings.APP_SEARCH_SETTINGS pkg=com.android.settings.intelligence cmp=com.android.settings.intelligence/.search.SearchActivity (has extras)} from uid 1000

清单文件下关于SearchActivity的声明如下:

        <activity
            android:name=".search.SearchActivity"
            android:exported="true"
            android:theme="@style/Theme.Settings.NoActionBar">
            <intent-filter priority="-1">
                <action android:name="com.android.settings.action.SETTINGS_SEARCH" />
                <action android:name="android.settings.APP_SEARCH_SETTINGS" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
  • SearchActivity会初始化搜索框,在初始化方法onCreate()中,实例化了一个SearchFragMent.
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search_main);
        // Keeps layouts in-place when keyboard opens.
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        FragmentManager fragmentManager = getFragmentManager();
        Fragment fragment = fragmentManager.findFragmentById(R.id.main_content);
        if (fragment == null) {
            fragmentManager.beginTransaction()
                    .add(R.id.main_content, new SearchFragment())
                    .commit();
        }

Note:FragmentManager是一个抽象类,根据findFragmentBtId找到对应的Fragment.

 

2.SearchFragment

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        long startTime = System.currentTimeMillis();
        setHasOptionsMenu(true);

        final LoaderManager loaderManager = getLoaderManager();
        mSearchAdapter = new SearchResultsAdapter(this /* fragment */);
        mSavedQueryController = new SavedQueryController(
                getContext(), loaderManager, mSearchAdapter);
        mSearchFeatureProvider.initFeedbackButton();

        if (savedInstanceState != null) {
            mQuery = savedInstanceState.getString(STATE_QUERY);
            mNeverEnteredQuery = savedInstanceState.getBoolean(STATE_NEVER_ENTERED_QUERY);
            mShowingSavedQuery = savedInstanceState.getBoolean(STATE_SHOWING_SAVED_QUERY);
        } else {
            mShowingSavedQuery = true;
        }
        mSearchFeatureProvider.updateIndexAsync(getContext(), this /* indexingCallback */);
        if (SearchFeatureProvider.DEBUG) {
            Log.d(TAG, "onCreate spent " + (System.currentTimeMillis() - startTime) + " ms");
        }
    }

onCreate()方法如上,创建了一些对象,以及通过 mSearchFeatureProvider.updateIndexAsync()方法初始化数据库.

  • SearchFragment还继承了SearchView的OnQueryTextListener接口,onQueryTextSubmit()只是保存了查询和隐藏软键盘的操作(提交按钮的点击事件,提交会回调此方法);重点来看看onQueryTextChange()方法(输入框内容改变的时候会回调).
    public interface OnQueryTextListener {
        boolean onQueryTextSubmit(String var1);

        boolean onQueryTextChange(String var1);
    }
  • onQueryTextChange( )
@Override
    public boolean onQueryTextChange(String query) {
        if (TextUtils.equals(query, mQuery)) {
            return true;
        }
        mEnterQueryTimestampMs = System.currentTimeMillis();
        final boolean isEmptyQuery = TextUtils.isEmpty(query);

        // Hide no-results-view when the new query is not a super-string of the previous
        if (mQuery != null
                && mNoResultsView.getVisibility() == View.VISIBLE
                && query.length() < mQuery.length()) {
            mNoResultsView.setVisibility(View.GONE);
        }

        mNeverEnteredQuery = false;
        mQuery = query;

        // If indexing is not finished, register the query text, but don't search.
        if (!mSearchFeatureProvider.isIndexingComplete(getActivity())) {
            return true;
        }

        if (isEmptyQuery) {
            final LoaderManager loaderManager = getLoaderManager();
            loaderManager.destroyLoader(SearchLoaderId.SEARCH_RESULT);
            mShowingSavedQuery = true;
            mSavedQueryController.loadSavedQueries();
            mSearchFeatureProvider.hideFeedbackButton(getView());
        } else {
            mMetricsFeatureProvider.logEvent(SettingsIntelligenceEvent.PERFORM_SEARCH);
            restartLoaders();
        }

        return true;
    }

我们可以清楚地看到当判断不是空查询的时候,会调用方法:restartLoaders().该方法主要通过抽象类LoaderManager的initLoader

去加载数据.

    private void restartLoaders() {
        mShowingSavedQuery = false;
        final LoaderManager loaderManager = getLoaderManager();
        loaderManager.restartLoader(
                SearchLoaderId.SEARCH_RESULT, null /* args */, this /* callback */);
    }
  • 当load成功之后,会回调onCreateLoader()
    @Override
    public Loader<List<? extends SearchResult>> onCreateLoader(int id, Bundle args) {
        final Activity activity = getActivity();

        switch (id) {
            case SearchLoaderId.SEARCH_RESULT:
                return mSearchFeatureProvider.getSearchResultLoader(activity, mQuery);
            default:
                return null;
        }
    }
  • 通过getSearchResultLoader()方法返回查询结果
    /**
     * Returns a new loader to get settings search results.
     */
    SearchResultLoader getSearchResultLoader(Context context, String query);
  • getSearchResultLoader()得到SearchResultLoader对象后,SearchResultLoader会在子线程中进行数据查找loadInBackground
    @Override
    public List<? extends SearchResult> loadInBackground() {
        SearchResultAggregator aggregator = SearchResultAggregator.getInstance();
        return aggregator.fetchResults(getContext(), mQuery);
    }
  • fetchResults()进行数据查找以及过滤.并且创建了一个SearchQueryTask集合,然后通过遍历的方式让task执行.之后将执行的结果返回到了taskResult结果集中.
@NonNull
    public synchronized List<? extends SearchResult> fetchResults(Context context, String query) {
        final SearchFeatureProvider mFeatureProvider = FeatureFactory.get(context)
                .searchFeatureProvider();
        final ExecutorService executorService = mFeatureProvider.getExecutorService();

        final List<SearchQueryTask> tasks =
                mFeatureProvider.getSearchQueryTasks(context, query);
        // Start tasks
        for (SearchQueryTask task : tasks) {
            executorService.execute(task);
        }

        // Collect results
        final Map<Integer, List<? extends SearchResult>> taskResults = new ArrayMap<>();
        final long allTasksStart = System.currentTimeMillis();
        for (SearchQueryTask task : tasks) {
            final int taskId = task.getTaskId();
            try {
                taskResults.put(taskId,
                        task.get(SHORT_CHECK_TASK_TIMEOUT_MS, TimeUnit.MILLISECONDS));
            } catch (TimeoutException | InterruptedException | ExecutionException e) {
                Log.d(TAG, "Could not retrieve result in time: " + taskId, e);
                taskResults.put(taskId, Collections.EMPTY_LIST);
            }
        }

        // Merge results
        final long mergeStartTime = System.currentTimeMillis();
        if (SearchFeatureProvider.DEBUG) {
            Log.d(TAG, "Total result loader time: " + (mergeStartTime - allTasksStart));
        }
        final List<? extends SearchResult> mergedResults = mergeSearchResults(taskResults);
        if (SearchFeatureProvider.DEBUG) {
            Log.d(TAG, "Total merge time: " + (System.currentTimeMillis() - mergeStartTime));
            Log.d(TAG, "Total aggregator time: " + (System.currentTimeMillis() - allTasksStart));
        }

        return mergedResults;
    }

 

 类似资料: