I am Using android.support.v7.widget.SearchView
and I am performing Search on enter of every character in SearchView. following is the 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 am updating the UI When I am Getting Result, So In My Case It will call Search API every time when user enter a single character. So Suppose user wants to Search "Australia" and try to enter whole word but My UI is Updating with Search and User has just type "Aus" after the Keyboard is not responding because it's updating the UI.
So I want Just want to respond Keyboard while Updating the UI.
Hope I'll get fast response.
5 Answers
Answers 1
The scenario of your case is:
Input text
Perform search
Display results
Do again
The lagging happened because of (2) + (3) cost much time to do.
Try to send the search key from (1) to worker thread (AsyncTask, Thread, IntentService,...).
(2) will be execute on worker thread then push the results back to UI
(3) update the UI
To improve performance, I think you should perform search while user stop the input at period of time. In additional, stop unneccessary search if the input changed.
example: input1 > search1 > input2 > cancel old task1 > search2 > ...
Hope it help!
Answers 2
The key to the problem is both updating UI operation with the result from Search API and responding to SearchView with Keyboard are do its job in Main(UI) Thread.
In a short, you let the main thread do too much thing in a short time.
So the solution is to try to LIMIT the frequency of updating UI operation. I meaning, you should let the displayResult(newText)
method can CANCEL the previous call when the user continuously inputted word in a short time.
Just updating the UI with the result ONCE when the whole word Australia
was inputted completely.
BTW, your search API call should do in the background thread with some wonderful library(Retrofit && OkHttp).
Answers 3
There might be two things that you might be doing wrong. 1) Network request are performed from UI Thread 2) Parsing is done on UI Thread Judging from your stackoverflow points you might not be doing the first case ie; performing a network request on the UI Thread.
For Case 2: try to perform parsing on a background thread, try to shorten the json response (tell the author of the Search API to give a lightweight response). And for each query change cancel the previous task
Answers 4
Your keyboard is not responding because displayResult
method is being executed on your main ui thread.
One of the possible solutions to handle this problem properly is using a IntentService
, for instance, you can do:
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 fetches data in background thread and sends data to your Activity
when some event occurs (start/end).
On your Activity
class, you need to do the following:
1. Declare a BroadcastReceiver
instance:
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 your BroadcastReceiver
:
@Override public void onResume(){ super.onResume(); registerReceiver(mReceiver, new IntentFilter(MyIntentService.SERVICE_BROADCAST)); } @Override public void onPause() { super.onPause(); unregisterReceiver(mReceiver); }
3. Start your 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:
Answers 5
Use TextWatcher in its afterTextChanged method write your search query and call refresh your view from there itself. Also,Use asynchronous way for making API calls so that your UI doesnt get stuck and you can load the response in your refreshView method .
0 comments:
Post a Comment