版权声明:本文为博主原创翻译文章,转载请注明出处。
推荐: 欢迎关注我创建的Android TV 简书专题,会定期给大家分享一些AndroidTv相关的内容:
###搜索功能实现
在前一章中介绍了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方法。 简单的实现已经完成了! 我们来尝试构建并运行代码。
搜索功能正常工作。我们已经完成了搜索功能的最低执行。 下一步是即使在用户的文本输入过程中也能启用搜索。 ###动态搜索执行
为了检测用户输入搜索查询的时间,我们可以使用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
可以看出,即使在用户输入搜索查询时,搜索仍然执行。 视频播放器
源代码在上。
关注微信公众号,定期为你推荐移动开发相关文章。