Home > Net >  How to show a LoadingDialog only if the operation takes too long?
How to show a LoadingDialog only if the operation takes too long?

Time:06-08

I do an API call in my Android App which can return a response almost immediatly or take a bit longer, before the API call i show my LoadingDialog and on response i dismiss it, the big issue of that is even if the response is immediate i show and dismiss the LoadingDialog and it seems like a "bug" as the screen shows and hides immediatly a dialog.

I would be able to show that dialog ONLY if the response take longer than 1 second to be returned.

Here is my code:

   public void AlertLoading() {
        Fragment fragment = getSupportFragmentManager().findFragmentByTag(LoadingDialog.TAG);
        if (fragment instanceof LoadingDialog) {
            ((LoadingDialog) fragment).dismissAllowingStateLoss();
        }else {
            new LoadingDialog().show(getSupportFragmentManager(), LoadingDialog.TAG);
        }
    }

    private void getTable(String tableNumber) {


        AlertLoading();

        Ion.with(getApplicationContext())
                .load("http://"   ip   "/webquery/?FINDTAV="   tableNumber   "&v2=true")
                .setTimeout(10000)
                .asString()
                .setCallback((e, result) -> {
                    AlertLoading();
                    // DOING STUFF
                });
    }

CodePudding user response:

Use Flows to receive api response and collect it inside coroutines

        viewModelScope.launch(Dispatchers.IO) {
                    repo.myApiFunc(param1, param2)
                        .onStart {
                            withContext(Dispatchers.Main) {
                                uiState.value = UiState.ProgressBar(true)
                            }
                        }
                        .catch {
                            withContext(Dispatchers.Main) {
                                uiState.value = UiState.ProgressBar(false)
                            }
                        }
                        .collect { response->
                            withContext(Dispatchers.Main) {
                                uiState.value = UiState.ProgressBar(false)
                                handleData(response)
                            }
                        }
                }

And Your repository function looks like this

suspend fun myApiFunc(param1: Any, param2: Any
    ): Flow<MyResponse> {
        return flow<MyResponse> {
            emit(apiHelper.apiCall(param1, param2))
        }
    }

and in your api call looks like

    @POST("Endpoint")
    suspend fun apiCall(
        @Field("email") email: String,
        @Field("password") password: String
    ): MyResponse

and your uistate variable is also of flow type that is collected inside fragment and displays the loader on receiving true while hides it on false

CodePudding user response:

As suggested by @Ricky Mo in comments i've followed the way of checking for Content-Lenght and if this is > than X bytes i'm showing the loading dialog.

I changed the code as following:

    private void getTable(String tableNumber) {

    // Doing an API call with HEAD method which returns Content-Lenght, if this is > than 10000 i'm showing the dialog



LoadingDialog.RetrofitClient.getInstance(ip).getApi().getTableLenght(tableNumber, true)
                    .enqueue(new Callback<Void>() {
                        @Override
                        public void onResponse(@NonNull Call<Void> call, @NonNull retrofit2.Response<Void> response) {
                            String contentLength = response.headers().get("Content-Length");
                            if (contentLength != null) { 
                                if (Double.parseDouble(contentLength) > 10000) { 
                                    showLoading(true);
                                }
                            }
                        }
    
                        @Override
                        public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
                            showLoading(false);
                        }
                    });
    
    // I've changed Ion with Retrofit for data parsing
        
Call<String> call = RetrofitClient.getInstance(ip).getApi().getTable(tableNumber, true);
            call.enqueue(new Callback<String>() {
                @Override
                public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
                    showLoading(false);
                    if (response.isSuccessful()) {
                     ... Doing stuff
                    }
                }
    
                @Override
                public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
                    showLoading(false);
                }
            });
        }
  • Related