NiceToMytyuk
NiceToMytyuk

Reputation: 4277

How to cancel all queued request onFailure? (Retrofit2)

Actually i'm using Retrofit2 in my app for sending some text to my server.

The issue is when i'm using a Radio Frequency Device when the network is interrupted so i'm getting onFailure the call should be cancelled but as soon as the device is reconnected to the network seems it's resending the text or something like that text remain in queue and i would handle it.

Here is my method where i'm sending the text ( i've yet tryed to use call.cancel() in onFailure but that has no effect )

  @SuppressLint("DefaultLocale")
    public void sendPost() {
        @SuppressLint({"SdCardPath", "DefaultLocale"}) final File file = new File("/data/data/app/files/"+String.format("%03d", Integer.valueOf(nTerminalino))+"_"+nTavoli.getText().toString()+".txt");

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);

        RequestBody fbody = RequestBody.create(MediaType.parse("text/*"), file);
        builder.addFormDataPart(String.format("%03d", Integer.valueOf(nTerminalino))+"_"+nTavoli.getText().toString(), file.getName(),fbody);

        MultipartBody requestBody = builder.build();

        final APIService apiService = ApiUtils.getAPIService(ipCASSA);

        final Call<Void> calls = apiService.savePost(requestBody);

        calls.enqueue(new Callback<Void>() {
            @Override
            public void onResponse(@NonNull Call<Void> call, @NonNull Response<Void> response) {
                if (response.isSuccessful()) {
                    Log.i("RESPONSE: ", response.toString());
                    Print();
                    file.delete();
                    dialogLoading.dismiss();
                    Runtime.getRuntime().gc();
                }else {
                    calls.cancel();
                }
            }

            @Override
            public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
                    Log.e("TAG", t.toString());
                    MediaPlayer mpFound = MediaPlayer.create(pterm.this, R.raw.errorsound);
                    mpFound.start();
                    Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                    if (v.hasVibrator()) {
                        v.vibrate(6000);
                    }
                    new GlideToast.makeToast(pterm.this, "CONNESSIONE FALLITA!", GlideToast.LENGTHLONG, GlideToast.FAILTOAST).show();
                    dialogLoading.dismiss();

            }
        });
    }

In my class where i'm building OkHttpClient i've set retryOnConnectionFailure(false) but still unable to solve the problem that even onFailure i'm getting the POST request.

UPDATE:

After some research i found that OkHttp make's silent retry of POST on connection failure.

So how can i prevent the client to retry?

SOME INFO:

My app is an app for waiter so when i get a onFailure message i notify the waiter that the receipt hasn't been received by POS and hasn't been printed but as OkHttpClient still retry to sending the file and i'm forcing the waiter to resend the receipt after onFailure it cause printing duplicated receipts.

Here is my ApiUtils class , APIService interface and RetrofitClient class

class ApiUtils {

    private ApiUtils() {}



    static APIService getAPIService(String ipCASSA) {

        String BASE_URL = "http://"+ipCASSA+"/web/";

        final OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10000, TimeUnit.MILLISECONDS)
                .writeTimeout(10000, TimeUnit.MILLISECONDS)
                .readTimeout(10000, TimeUnit.MILLISECONDS)
                .retryOnConnectionFailure(false)
                .build();


        return RetrofitClient.getClient(BASE_URL,okHttpClient).create(APIService.class);
    }
}

public interface APIService {

    @POST("CART=PTERM")
    Call<Void> savePost(@Body RequestBody text);

}

class RetrofitClient {

    private static Retrofit retrofit = null;


    static Retrofit getClient(String baseUrl, OkHttpClient okHttpClient) {
        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .client(okHttpClient)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

Upvotes: 6

Views: 1342

Answers (2)

crymson
crymson

Reputation: 1190

You could try canceling the call directly. So when the call fails, in the onFailure callback, you can do something like

@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
    if (!call.isCanceled()) {
        // Do receipt logic
        call.cancel();
    }
}

Upvotes: 1

Bertram Gilfoyle
Bertram Gilfoyle

Reputation: 10235

Since retryOnConnectionFailure(false) didn't help, the problem is not caused by OKHttp retry.

I suspect you are duplicating the request. Check whether sendPost() is getting called multiple times.

Upvotes: 0

Related Questions