Answer the keyboard when updating the user interface

I use android.support.v7.widget.SearchView , and I do a search to enter each character in the SearchView. Below is a snippet.

 searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { if (!newText.trim().equals("")) { displayResult(newText); return false; } } }); 

And I update the user interface when I get the result, so in my case It will call the search API every time the user enters a single character. So, suppose the user wants to find "Australia" and try to enter the whole word, but my user interface is updated when searching, and the user simply types "Aus" after the keyboard does not respond, because it updates the user interface.

So I want to just want to answer the keyboard when updating the user interface.
I hope I get a quick reply.

+5
source share
5 answers

Scenario of your case:

  • Input text

  • Search

  • Show results

  • Do it again

The delay was due to (2) + (3), which cost a lot of time.

Try sending the search key from (1) to the workflow (AsyncTask, Thread, IntentService, ...).

(2) will be executed in the workflow, and then return the results back to the user interface

(3) update user interface

To improve performance, I think you should do a search while the user stops entering for a certain period of time. In addition, stop unnecessary searching if the input has changed.

example: input1> search1> input2> undo the old task1> search2> ...

Hope this helps!

+2
source

The key to the problem is both updating the user interface operation with the result of the API search and the response to the SearchView with the keyboard, doing their job in the Main (UI) thread theme.

In short, you let the main thread do too many things in a short time.

Therefore, the solution is to try to LIMIT the user interface refresh rate. In the sense, you should allow the displayResult(newText) method to CANCEL the previous call when the user will enter a word for a short time.

Just update the user interface with the ONCE result when all Australia has been fully entered.

By the way, your search API request should do in the background thread with a wonderful library ( Retrofit && OkHttp ).

+1
source

Perhaps there are two things you could do wrong. 1) The network request is made from the user interface thread 2) The analysis is performed on the UI Thread page Judging by your stackoverflow points, you may not be making the first case ie; executing a network request in a user interface thread.

For case 2: try parsing in the background thread, try shortening the json response (tell the author of the search API to give an easy answer). And for each request change cancel the previous task

+1
source

Your keyboard is not responding because displayResult is displayResult in your main ui displayResult .

One possible solution to handle this problem correctly is to use an IntentService , for example, you can:

MyIntentService.java

 public class MyIntentService extends IntentService { //Each of these results represent a possible status of your service public static final int RESULT_ERROR = -1; public static final int RESULT_ENDED = 1; public static final int RESULT_START = 0; public static final String SERVICE_BROADCAST = MyIntentService.class.getName()+".Broadcast"; public MigrateService(){ super(MigrateService.class.getName()); } @Override protected void onHandleIntent(Intent intent) { //Get the query String queryText = intent.getStringExtra("MyQuery"); //Notify the activity that search has started publishResult(RESULT_START, Bundle.EMPTY); Bundle data = null; try{ data = getDataWithRetrofit(queryText); } catch (SomeException e){ //In case of error, notify the activity publishResult(RESULT_ERROR, Bundle.EMPTY); } //Search is ended publishResult(RESULT_ENDED, data); } public void publishResult(int resultCode, Bundle data){ Intent intent = new Intent(SERVICE_BROADCAST); intent.putExtras(data); intent.putExtra("resultCode",resultCode); sendBroadcast(intent); } } 

Basically, you have a Service that retrieves data in a background thread and sends data to your Activity when some kind of event (start / end) occurs.

In your Activity class, you need to do the following:

1. Declare an instance of BroadcastReceiver :

 private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if(intent.hasExtra("resultCode")) { int resultCode = intent.getIntExtra("resultCode",MyService.STATUS_ERROR); switch (resultCode) { case MyIntentService.RESULT_START: showIndeterminateProgress(); break; case MyIntentService.RESULT_ENDED: updateResultList(data); break; case MyIntentService.RESULT_ERROR: showErrorMessage(); break; } } } }; 

2. Register and unregister BroadcastReceiver :

 @Override public void onResume(){ super.onResume(); registerReceiver(mReceiver, new IntentFilter(MyIntentService.SERVICE_BROADCAST)); } @Override public void onPause() { super.onPause(); unregisterReceiver(mReceiver); } 

3. Start the service:

 searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { if (!newText.trim().equals("")) { Intent i = new Intent(this, MyIntentService.class); i.putExtra("MyQuery",newText); startService(i); return false; } } }); 

Sources:

0
source

Use TextWatcher in your afterTextChanged method to write your search query and trigger an update of your view from there. Alternatively, use the asynchronous method to create API calls so that your user interface does not get stuck and you can load the response into your refreshView method.

0
source

All Articles