如何使用http请求在actionbar中实现搜索视图自动完成?

时间:2022-10-05 14:31:28

I've add search view widget to my action bar and would like to handle autocomplete feature. After writing more then 3 letters it should fulfill http request to my web API which will return json result and should show search widget suggestions. But in documentation is observed the case with content providers. How can I organize autocomplete feature?

我已经将search view小部件添加到我的操作栏中,并希望处理自动完成功能。在写了超过3个字母后,它应该完成对我的web API的http请求,该API将返回json结果并显示搜索小部件建议。但是在文档中可以观察到内容提供者的情况。如何组织自动完成功能?

Added search view in menu xml file:

在菜单xml文件中添加搜索视图:

    <item android:id="@+id/search"
    android:icon="@drawable/ic_search_white_24dp"
    android:title="Search"
    [namespace]:showAsAction="always"
    [namespace]:actionViewClass="android.widget.SearchView" />

Associates searchable configuration with the SearchView:

关联可搜索配置与SearchView:

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.navigation, menu);

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

    return super.onCreateOptionsMenu(menu);
}

Added searchable configuration:

添加搜索配置:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="@string/search_hint"
    android:searchSuggestAuthority="com.my.domain.searchable_activity" />

And ultimately added empty responsible activity.

最终增加了空的负责任的活动。

1 个解决方案

#1


15  

You can't do this with setSearchableInfo() and a search configuration.

对于setSearchableInfo()和搜索配置,您不能这样做。

The problem is that SearchView needs a CursorAdapter and you are retrieving data from the server, not the database.

问题是SearchView需要一个CursorAdapter,您正在从服务器检索数据,而不是数据库。

However, I have done something like this before with these steps:

然而,我以前就做过这样的事情:

  • Set up your SearchView to use a CursorAdapter;

    设置SearchView以使用CursorAdapter;

        searchView.setSuggestionsAdapter(new SimpleCursorAdapter(
                context, android.R.layout.simple_list_item_1, null, 
                new String[] { SearchManager.SUGGEST_COLUMN_TEXT_1 }, 
                new int[] { android.R.id.text1 }));
    
  • Create an AsyncTask to read the JSON data from your server and create a MatrixCursor from the data:

    创建一个AsyncTask从服务器读取JSON数据,并从数据中创建一个MatrixCursor:

    public class FetchSearchTermSuggestionsTask extends AsyncTask<String, Void, Cursor> {
    
        private static final String[] sAutocompleteColNames = new String[] { 
                BaseColumns._ID,                         // necessary for adapter
                SearchManager.SUGGEST_COLUMN_TEXT_1      // the full search term
        };
    
        @Override
        protected Cursor doInBackground(String... params) {
    
            MatrixCursor cursor = new MatrixCursor(sAutocompleteColNames);
    
            // get your search terms from the server here, ex:
            JSONArray terms = remoteService.getTerms(params[0]);
    
            // parse your search terms into the MatrixCursor
            for (int index = 0; index < terms.length(); index++) {
                String term = terms.getString(index);
    
                Object[] row = new Object[] { index, term };
                cursor.addRow(row);
            }
    
            return cursor;
        }
    
        @Override
        protected void onPostExecute(Cursor result) {
            searchView.getSuggestionsAdapter().changeCursor(result);
        }
    
    }
    
  • Set an OnQueryTextListener to kick off your remote server task or start your search activity:

    设置一个OnQueryTextListener以启动远程服务器任务或启动搜索活动:

        searchView.setOnQueryTextListener(new OnQueryTextListener() {
    
            @Override
            public boolean onQueryTextChange(String query) {
    
                if (query.length() >= SEARCH_QUERY_THRESHOLD) {
                    new FetchSearchTermSuggestionsTask().execute(query);
                } else {
                    searchView.getSuggestionsAdapter().changeCursor(null);
                }
    
                return true;
            }
    
            @Override
            public boolean onQueryTextSubmit(String query) {
    
                // if user presses enter, do default search, ex:
                if (query.length() >= SEARCH_QUERY_THRESHOLD) {
    
                    Intent intent = new Intent(MainActivity.this, SearchableActivity.class);
                    intent.setAction(Intent.ACTION_SEARCH);
                    intent.putExtra(SearchManager.QUERY, query);
                    startActivity(intent);
    
                    searchView.getSuggestionsAdapter().changeCursor(null);
                    return true;
                }
            }
        });
    
  • Set an OnSuggestionListener on the SearchView to execute your search:

    在SearchView上设置一个on合理化监听器来执行您的搜索:

        searchView.setOnSuggestionListener(new OnSuggestionListener() {
    
            @Override
            public boolean onSuggestionSelect(int position) {
    
                Cursor cursor = (Cursor) searchView.getSuggestionsAdapter().getItem(position);
                String term = cursor.getString(cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
                cursor.close();
    
                Intent intent = new Intent(MainActivity.this, SearchableActivity.class);
                intent.setAction(Intent.ACTION_SEARCH);
                intent.putExtra(SearchManager.QUERY, term);
                startActivity(intent);
    
                return true;
            }
    
            @Override
            public boolean onSuggestionClick(int position) {
    
                return onSuggestionSelect(position);
            }
        });
    

#1


15  

You can't do this with setSearchableInfo() and a search configuration.

对于setSearchableInfo()和搜索配置,您不能这样做。

The problem is that SearchView needs a CursorAdapter and you are retrieving data from the server, not the database.

问题是SearchView需要一个CursorAdapter,您正在从服务器检索数据,而不是数据库。

However, I have done something like this before with these steps:

然而,我以前就做过这样的事情:

  • Set up your SearchView to use a CursorAdapter;

    设置SearchView以使用CursorAdapter;

        searchView.setSuggestionsAdapter(new SimpleCursorAdapter(
                context, android.R.layout.simple_list_item_1, null, 
                new String[] { SearchManager.SUGGEST_COLUMN_TEXT_1 }, 
                new int[] { android.R.id.text1 }));
    
  • Create an AsyncTask to read the JSON data from your server and create a MatrixCursor from the data:

    创建一个AsyncTask从服务器读取JSON数据,并从数据中创建一个MatrixCursor:

    public class FetchSearchTermSuggestionsTask extends AsyncTask<String, Void, Cursor> {
    
        private static final String[] sAutocompleteColNames = new String[] { 
                BaseColumns._ID,                         // necessary for adapter
                SearchManager.SUGGEST_COLUMN_TEXT_1      // the full search term
        };
    
        @Override
        protected Cursor doInBackground(String... params) {
    
            MatrixCursor cursor = new MatrixCursor(sAutocompleteColNames);
    
            // get your search terms from the server here, ex:
            JSONArray terms = remoteService.getTerms(params[0]);
    
            // parse your search terms into the MatrixCursor
            for (int index = 0; index < terms.length(); index++) {
                String term = terms.getString(index);
    
                Object[] row = new Object[] { index, term };
                cursor.addRow(row);
            }
    
            return cursor;
        }
    
        @Override
        protected void onPostExecute(Cursor result) {
            searchView.getSuggestionsAdapter().changeCursor(result);
        }
    
    }
    
  • Set an OnQueryTextListener to kick off your remote server task or start your search activity:

    设置一个OnQueryTextListener以启动远程服务器任务或启动搜索活动:

        searchView.setOnQueryTextListener(new OnQueryTextListener() {
    
            @Override
            public boolean onQueryTextChange(String query) {
    
                if (query.length() >= SEARCH_QUERY_THRESHOLD) {
                    new FetchSearchTermSuggestionsTask().execute(query);
                } else {
                    searchView.getSuggestionsAdapter().changeCursor(null);
                }
    
                return true;
            }
    
            @Override
            public boolean onQueryTextSubmit(String query) {
    
                // if user presses enter, do default search, ex:
                if (query.length() >= SEARCH_QUERY_THRESHOLD) {
    
                    Intent intent = new Intent(MainActivity.this, SearchableActivity.class);
                    intent.setAction(Intent.ACTION_SEARCH);
                    intent.putExtra(SearchManager.QUERY, query);
                    startActivity(intent);
    
                    searchView.getSuggestionsAdapter().changeCursor(null);
                    return true;
                }
            }
        });
    
  • Set an OnSuggestionListener on the SearchView to execute your search:

    在SearchView上设置一个on合理化监听器来执行您的搜索:

        searchView.setOnSuggestionListener(new OnSuggestionListener() {
    
            @Override
            public boolean onSuggestionSelect(int position) {
    
                Cursor cursor = (Cursor) searchView.getSuggestionsAdapter().getItem(position);
                String term = cursor.getString(cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
                cursor.close();
    
                Intent intent = new Intent(MainActivity.this, SearchableActivity.class);
                intent.setAction(Intent.ACTION_SEARCH);
                intent.putExtra(SearchManager.QUERY, term);
                startActivity(intent);
    
                return true;
            }
    
            @Override
            public boolean onSuggestionClick(int position) {
    
                return onSuggestionSelect(position);
            }
        });