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);
}
});
}