Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
    }
}
like image 596
NiceToMytyuk Avatar asked Dec 14 '18 13:12

NiceToMytyuk


People also ask

How do I cancel my retrofit API call?

Calls may be executed synchronously with execute() , or asynchronously with enqueue(retrofit2. Callback<T>) . In either case the call can be canceled at any time with cancel() . A call that is busy writing its request or reading its response may receive a IOException ; this is working as designed.

Is Retrofit asynchronous?

Learn to execute synchronous and asynchronous calls (i.e. blocking and non-blocking calls) in an android app using Retrofit2 and OkHttp library.


1 Answers

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();
    }
}
like image 121
crymson Avatar answered Oct 10 '22 17:10

crymson