Search code examples
androidandroid-asynctaskandroid-actionbarsearchview

SearchView AsyncTask UI Not Updating Properly


I have a problem with implementing searchview showing its results for data coming from a server. I currently use an AsyncTask so that I don't block the UI. Here's how I implemented it:

searchView.setOnQueryTextListener(new OnQueryTextListener() {

    @Override
    public boolean onQueryTextChange(String query) {

        if (query.length() > 0) {
            new GetSearchByNameResultTask(searchView).execute(query);
        } else {
            return false;
        }

        return true;
    }

    @Override
    public boolean onQueryTextSubmit(String arg0) {
        // TODO Auto-generated method stub
        return false;
    }

});

GetSearchByNameResultTask

class GetSearchByNameResultTask extends AsyncTask<String, Void, String> {

    private SearchView searchView;

    public GetSearchByNameResultTask(SearchView searchView) {
        this.searchView = searchView;
    }

    @Override
    protected String doInBackground(String... params) {
        // TODO Auto-generated method stub
        return WebRequestHelper.getInfo(params[0]);
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        AppLog.d(TAG, "Result search: " + result);
        Gson gson = new Gson();

        searchResponseList = gson.fromJson(result, new TypeToken<List<Info>>() {
        }.getType());

        loadHistory(searchView, searchResponseList);
        // TODO: search adapter
    }
}

loadHistory() code:

private void loadHistory(SearchView searchView, List<AppInfo> searchResponse) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        searchView.setSuggestionsAdapter(null);
        // Cursor
        String[] columns = new String[] { "_id", "text" };
        Object[] temp = new Object[] { 0, "default" };

        MatrixCursor cursor = new MatrixCursor(columns);

        final List<Info> items = searchResponse;

        for (int i = 0; i < items.size(); i++) {

            temp[0] = i;
            temp[1] = items.get(i).getName();
            cursor.addRow(temp);
        }
        CursorAdapter ca = new AppListSearchAdapter(this, cursor, items);
        new AsyncQueryResult(cursor,ca).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
        // SearchView
        searchView.refreshDrawableState();
        searchView.setSuggestionsAdapter(ca);
        searchView.setOnSuggestionListener(new OnSuggestionListener() {

            @Override
            public boolean onSuggestionSelect(int position) {
                // TODO Auto-generated method stub
                return false;
            }

        });
    }
}

Problem Everything runs alright. I'm getting the search results. But I have a problem updating the views. Probably best explained with an example:

Data:

Hell
Hello
Helicopter

text in search: Hel

Result:

Hello World
Hello
Helicopter

text in search: Hell

Hell
Hello
[extra empty space] 

the extra empty space is my problem. The "listview" doesn't get updated to fit the results until I type 'Hello'


Solution

  • I forgot to answer this question.

    I managed to fix this issue, although it was a bit of a hack on my part. Here's what I did:

        @Override
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        searchAdapter = new SearchAdapter(this,  cursor, false);
    
        mSearchView.setSuggestionsAdapter(searchAdapter );
    
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                searchAdapter.notifyDataSetChanged();
            }
        }, 200);
    
        //Reload fragment to show list
    }
    

    This would force to refresh the search view's adapter. The new Handler().postDelayed() was the key here.

    Hope this solution helps.