英文:
Wait until Retrofit enque will be executed
问题
I have async call to server with this structure:
AuthAPI authAPI = retrofitService.getRetrofit().create(AuthAPI.class);
authAPI.registerUser(requestBody)
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call,
@NonNull Response<ResponseBody> response) {
// Response processing.
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call,
@NonNull Throwable t) {
// Failure processing.
}
});
This code is executed inside onClick()
method of a button. After this code a new Fragment is replacing the current, but when this code executes due to .enqueue()
is async the async part is not finished yet, so application is crashing. So, I need to wait until async code is executed and then show new fragment.
I could use execute()
method instead of enqueue()
method, but if I understand it right, until execute()
method is finished the whole UI thread will be frozen, and ProgressBar animation will not run. That is also bad for me.
So, what I am asking is, how could I wait for the server response to be processed and not lock my UI thread so the ProgressBar can keep spinning?
英文:
I have async call to server with this structure:
AuthAPI authAPI = retrofitService.getRetrofit().create(AuthAPI.class);
authAPI.registerUser(requestBody)
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call,
@NonNull Response<ResponseBody> response) {
// Response processing.
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call,
@NonNull Throwable t) {
// Failure processing.
}
});
This code is executed inside onClick()
method of a button. After this code a new Fragment is replacing the current, but when this code executes due to .enqueue()
is async the async part is not finished yet, so application is crashing. So, I need to wait until async code is executed and then show new fragment.
I could use execute()
method instead of enqueue()
method, but if I understand it right, until execute()
method is finished the whole UI thread will be frozen and ProgressBar animation will not run. That is also bad for me.
So, what I am asking is, how could I wait for server response to be processed and dont lock my UI-thread so ProgressBar was spinning?
答案1
得分: 0
你不要在主线程上等待异步函数完成。这样做最好会导致你的应用程序冻结并且无响应,最坏的情况下会引发ANR并崩溃。相反,你想要在异步代码之后执行的任何操作都应该放在异步回调中,在onResponse
或onFailure
块中。
英文:
You don't ever wait for an async function to finish on the main thread. Doing so will at best make your app freeze and be unresponsive, at worst cause an ANR and crash. Instead, anything you want to do after the async code should be put in the async callback- in the onResponse or onFailure block.
答案2
得分: 0
是的,你应该在开始之前显示一些进度条,然后在onResponse
中隐藏它,在此之后,你可以显示你的片段,以下是一些代码:
progressBar.setVisibility(View.VISIBLE);
authAPI.registerUser(requestBody).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call,
@NonNull Response<ResponseBody> response) {
// 处理响应。
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE); // 当接收到响应时隐藏进度条
// 在此处用新片段替换当前片段
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
NewFragment newFragment = new NewFragment();
fragmentTransaction.replace(R.id.fragment_container, newFragment);
fragmentTransaction.commit();
}
});
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call,
@NonNull Throwable t) {
// 失败处理。
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE); // 当响应失败时隐藏进度条
}
});
}
});
使用runOnUiThread
的原因是确保视图更新和片段事务发生在主UI线程上,而不是在enqueue
操作所在的后台线程上,以防止引发异常!
英文:
Yes, you should show some Progressbar before starting, then hide it in the onResponse
, and after that, you can show your fragment, here is some code:
progressBar.setVisibility(View.VISIBLE);
authAPI.registerUser(requestBody).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call,
@NonNull Response<ResponseBody> response) {
// Response processing.
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE); // hide progress bar when response is received
// Replace the current fragment with the new fragment here
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
NewFragment newFragment = new NewFragment();
fragmentTransaction.replace(R.id.fragment_container, newFragment);
fragmentTransaction.commit();
}
});
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call,
@NonNull Throwable t) {
// Failure processing.
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE); // hide progress bar when response fails
}
});
}
});
The reason for using runOnUiThread
is to ensure the View Updates and fragment transaction will happen on the main UI thread and not on the background thread that the enqueue
operation works on, so it doesn't raise an exception!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论