等待直到 Retrofit 的 enque 执行完成。

huangapple go评论72阅读模式
英文:

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并崩溃。相反,你想要在异步代码之后执行的任何操作都应该放在异步回调中,在onResponseonFailure块中。

英文:

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&lt;ResponseBody&gt;() {
    @Override
    public void onResponse(@NonNull Call&lt;ResponseBody&gt; call,
                           @NonNull Response&lt;ResponseBody&gt; 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&lt;ResponseBody&gt; 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!

huangapple
  • 本文由 发表于 2023年5月7日 23:03:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76194693.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定