5

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.

GreenROBO
  • 4,725
  • 4
  • 23
  • 43

5 Answers5

2

The scenario of your case is:

  1. Input text

  2. Perform search

  3. Display results

  4. 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!

Alex Hong
  • 281
  • 1
  • 11
1

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).

JohnWatsonDev
  • 1,227
  • 9
  • 16
1

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

NIPHIN
  • 1,071
  • 1
  • 8
  • 16
0

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:

Vektor88
  • 4,841
  • 11
  • 59
  • 111
0

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 .

Anurag
  • 1,162
  • 6
  • 20