美文网首页Android TVAndroidTV开发Android TV开发
[译]应用内搜索功能实现 - Android TV应用程序手册教

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

作者: wenju_song | 来源:发表于2017-07-05 16:43 被阅读256次

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

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


    搜索功能实现

    在前一章中介绍了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<String, Void, ListRow>() {
                private final String query = mQuery;
    
                @Override
                protected void onPreExecute() {
                    mRowsAdapter.clear();
                }
    
                @Override
                protected ListRow doInBackground(String... params) {
                    final List<Movie> 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方法。 简单的实现已经完成了! 我们来尝试构建并运行代码。


    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上。

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


    songwenju

    相关文章

      网友评论

        本文标题:[译]应用内搜索功能实现 - Android TV应用程序手册教

        本文链接:https://www.haomeiwen.com/subject/chqnfxtx.html