Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cancel the request using OKHTTP

I need to be able to MANAGER some requests with OKHTTP, using the Google Places AutoComplete to receive some predictions by typing the Address. The Problem is Each time that I insert a CHAR it will make a new request but at the same time I need to cancel the previous one! Ex : New York City = 13 Requests at the same time! So I'm using a single instance of Call trying to cancel anything that has been requested but with no success. This is what I did!

Address.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            if(Address.getText().toString().length() > 3){
                _Address = Address.getText().toString();
                if(call != null){
                    call.cancel();
                }
                Request request = new Request.Builder()
                        .url(getPlaceAutoCompleteUrl(_Address))
                        .addHeader("content-type", "application/json")
                        .addHeader("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; google_sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30")
                        .build();
                call = client.newCall(request);


                call.enqueue(new Callback() {
                    public void onResponse(Call call, final Response response) throws IOException {
                        final String result = response.body().string();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Log.d("Response",result);
                                PlacePredictions place = null;
                                try {
                                    place = LoganSquare.parse(result,PlacePredictions.class);
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                                if(autoCompleteAdapter == null){
                                    autoCompleteAdapter = new AutoCompleteAdapter(CustomPlaces.this);
                                    recyclerView.setAdapter(autoCompleteAdapter);
                                    autoCompleteAdapter.Add(place.getPlaces());
                                }else {
                                    autoCompleteAdapter.Clear();
                                    autoCompleteAdapter.Add(place.getPlaces());
                                    autoCompleteAdapter.notifyDataSetChanged();
                                }
                            }
                        });
                    }
                    public void onFailure(Call call, IOException e) {
                        //fail();
                    }
                });
            }else {
                if(autoCompleteAdapter != null){
                    autoCompleteAdapter.Clear();
                }
            }
        }

I check if the call object is null and cancel the request but still keeps coming!

like image 348
Nathiel Barros Avatar asked Sep 28 '17 19:09

Nathiel Barros


2 Answers

What about the following:

            //Set tags for your requests when you build them:
            Request request = new Request.Builder().
            url(url).tag("requestKey").build();

            //When you want to cancel:
            //A) go through the queued calls and cancel if the tag matches:
            for (Call call : mHttpClient.dispatcher().queuedCalls()) {
                if (call.request().tag().equals("requestKey"))
                    call.cancel();
            }

            //B) go through the running calls and cancel if the tag matches:
            for (Call call : mHttpClient.dispatcher().runningCalls()) {
                if (call.request().tag().equals("requestKey"))
                    call.cancel();
            }
like image 139
TomerBu Avatar answered Sep 19 '22 06:09

TomerBu


Delay request to server and post it only if input didn't changed for the timeout (1000 ms, adjust for better feel). You can add cancelation method to GetHintsRequest

...
    Address.addTextChangedListener(new TextWatcher() {
        @Override
        public void afterTextChanged(Editable s) {
            if (s.length() < 3) {
                if (autoCompleteAdapter != null) {
                    autoCompleteAdapter.Clear();
                }
                return;
            }

            GetHintsRequest request = new GetHintsRequest(s.toString(), new GetHintsRequest.GetHintsCallback() {
                @Override
                public boolean isRequestNotChanged(String oldRequest) {
                    return Address.getText().toString().equals(oldRequest);
                }

                @Override
                public void onGotHints(String request, PlacePredictions predictions) {
                    if (autoCompleteAdapter == null) {
                        autoCompleteAdapter = new AutoCompleteAdapter(CustomPlaces.this);
                        recyclerView.setAdapter(autoCompleteAdapter);
                        autoCompleteAdapter.Add(place.getPlaces());
                    } else {
                        autoCompleteAdapter.Clear();
                        autoCompleteAdapter.Add(place.getPlaces());
                        autoCompleteAdapter.notifyDataSetChanged();
                    }
                }
            });
            request.postCheck();
        }
    });
...

public class GetHintsRequest {
    private static final long TIMEOUT_MS = 1000; // timeout
    private final String requestText;
    private final GetHintsCallback callback;
    // android.os.Handler, can be used to post and delayed post to main thread. activity.runOnUiThread uses it
    private final Handler handler = new Handler(Looper.getMainLooper());

    public GetHintsRequest(String requestText, GetHintsCallback callback) {
        this.requestText = requestText;
        this.callback = callback;
    }

    public void postCheck() {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (callback.isRequestNotChanged(requestText)){
                    execute();
                }
            }
        }, TIMEOUT_MS);
    }


    public void execute() {
        Request request = new Request.Builder()
                .url(getPlaceAutoCompleteUrl(_Address))
                .addHeader("content-type", "application/json")
                .addHeader("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; google_sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30")
                .build();
        call = client.newCall(request);

        call.enqueue(new Callback() {
            public void onResponse(Call call, final Response response) throws IOException {
                final String result = response.body().string();
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Log.d("Response", result);
                        PlacePredictions place = null;
                        if (callback.isRequestNotChanged(requestText)) {
                            try {
                                place = LoganSquare.parse(result, PlacePredictions.class);
                            } catch (IOException e) {
                                e.printStackTrace();
                                return;
                            }
                            callback.onGotHints(requestText, place);
                        }
                    }
                });
            }

            public void onFailure(Call call, IOException e) {
                //fail();
            }
        });
    }

    public interface GetHintsCallback {
        boolean isRequestNotChanged(String oldRequest);

        void onGotHints(String request, PlacePredictions predictions);
    }

}
like image 41
babay Avatar answered Sep 17 '22 06:09

babay