[译]应用内搜索功能实现 - Android TV应用程序手册教程十三

版权声明:本文为博主原创翻译文章,转载请注明出处。

推荐:
欢迎关注我创建的Android TV 专题,会定期给大家分享一些AndroidTv相关的内容:
https://www.jianshu.com/c/3f0ab61a1322


搜索功能实现

在前一章中介绍了Leanback支持库和UI相关实现的SearchFragment的用法。 在本章中,我将介绍(背景)搜索功能逻辑。

本章的大部分实现仅仅是对googlesamples的解释 。

应用内搜索算法

搜索算法在loadRows方法中实现,特别是主逻辑在AsyncTask的doInBackground方法中。 其实很简单,只需检查字符串“ 查询 ”是否包含在电影项目的标题或描述中。

UI相关任务适配器处理在UI线程中完成。 onPreExecute通过clear方法初始化包含搜索结果的mRowsAdapter。 搜索本身在doInBackground中的后台线程中执行 ,它使包含搜索结果的新的ListRow 。 这个listRow是通过onPostExecute方法添加到UI线程中的Adapter 。

SearchFragment.java

    private void loadRows() {
        // offload processing from the UI thread
        new AsyncTask() {
            private final String query = mQuery;

            @Override
            protected void onPreExecute() {
                mRowsAdapter.clear();
            }

            @Override
            protected ListRow doInBackground(String... params) {
                final List result = new ArrayList<>();
                for (Movie movie : mItems) {
                    // Main logic of search is here. 
                    // Just check that "query" is contained in Title or Description or not.
                    if (movie.getTitle().toLowerCase(Locale.ENGLISH)
                            .contains(query.toLowerCase(Locale.ENGLISH))
                            || movie.getDescription().toLowerCase(Locale.ENGLISH)
                            .contains(query.toLowerCase(Locale.ENGLISH))) {
                        result.add(movie);
                    }
                }

                ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new CardPresenter());
                listRowAdapter.addAll(0, result);
                HeaderItem header = new HeaderItem("Search Results");
                return new ListRow(header, listRowAdapter);
            }

            @Override
            protected void onPostExecute(ListRow listRow) {
                mRowsAdapter.add(listRow);
            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

执行搜索

由于上面已经实现了搜索算法,我们只需要调用这个函数来获得搜索结果。

SearchFragment.java

    @Override
    public ObjectAdapter getResultsAdapter() {
        Log.d(TAG, "getResultsAdapter");
        // Delete previously implemented mock code.
        // mRowsAdapter (Search result) is already prepared in loadRows method
        return mRowsAdapter;
    }

    ...

    @Override
    public boolean onQueryTextSubmit(String query) {
        Log.i(TAG, String.format("Search Query Text Submit %s", query));
        mQuery = query;
        loadRows();
        return true;
    }

在onQueryTextSubmit方法中调用loadRows方法。 简单的实现已经完成了! 我们来尝试构建并运行代码。


[译]应用内搜索功能实现 - Android TV应用程序手册教程十三_第1张图片
search2

搜索功能正常工作。

我们已经完成了搜索功能的最低执行。 下一步是即使在用户的文本输入过程中也能启用搜索。

动态搜索执行

为了检测用户输入搜索查询的时间,我们可以使用onQueryTextChange方法。 因此,基本概念是在onQueryTextChange中执行loadRows方法来实现动态(在用户输入期间)搜索。 但是,每当用户输入一个单词时,onQueryTextChange将被执行,并且在已经执行的时候不应该调用loadRows方法。 这里,Handler用于管理执行的loadRows方法。

SearchFragment.java

    private static final long SEARCH_DELAY_MS = 1000L;

    private final Handler mHandler = new Handler();
    private final Runnable mDelayedLoad = new Runnable() {
        @Override
        public void run() {
            loadRows();
        }
    };

     ...

    /**
     * Starts {@link #loadRows()} method after delay.
     * @param query the word to be searched
     * @param delay the time to wait until loadRows will be executed (milliseconds).
     */
    private void loadQueryWithDelay(String query, long delay) {
        mHandler.removeCallbacks(mDelayedLoad);
        if (!TextUtils.isEmpty(query) && !query.equals("nil")) {
            mQuery = query;
            mHandler.postDelayed(mDelayedLoad, delay);
        }
    }

loadQueryWithDelay方法使用Handler以稍微延迟的方式发布loadRows任务,以便loadRows任务不会太频繁地执行。 最后一个修改是从onQueryTextChange调用此loadQueryWithDelay方法。

SearchFragment.java

    @Override
    public boolean onQueryTextChange(String newQuery){
        Log.i(TAG, String.format("Search Query Text Change %s", newQuery));
        loadQueryWithDelay(newQuery, SEARCH_DELAY_MS);
        return true;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        Log.i(TAG, String.format("Search Query Text Submit %s", query));
        // No need to delay(wait) loadQuery, since the query typing has completed.
        loadQueryWithDelay(query, 0);
        return true;
    }

Build and run

auto search

可以看出,即使在用户输入搜索查询时,搜索仍然执行。
视频播放器

源代码在github上。

关注微信公众号,定期为你推荐移动开发相关文章。


[译]应用内搜索功能实现 - Android TV应用程序手册教程十三_第2张图片
songwenju

你可能感兴趣的:([译]应用内搜索功能实现 - Android TV应用程序手册教程十三)