在异步操作中等待retrofit2完成的最佳方法是什么?

5

我知道类似的问题已经被问过,但是我对Android开发还很陌生,因此有些答案对我来说有点难以理解。我已经查看了CountDownLatch和使用线程的方法,但不确定该使用哪种方法。希望能得到帮助。我还尝试了在SharedPreferences中使用apply()而非commit()。

我正在从LoginActivity中进行两个retrofit2调用。我需要第一个调用返回的token来使用第二个调用。我在第一个retrofit调用的onResponse方法中将token保存到SharedPreferences中的字符串中。

在我的第二个调用中,serverToken的值返回为上一次应用程序运行时设置的token。

第一个调用(getToken)onResponse

   call.enqueue(new retrofit2.Callback<TokenResponse>() {    

            @Override
            public void onResponse(Call<TokenResponse> call, retrofit2.Response<TokenResponse> response) {

                if (response.isSuccessful()) {
                    TokenResponse tokenResponse = response.body();

                    LoginActivity.editor.putString("serverToken", tokenResponse.getAccessToken());
                    LoginActivity.editor.commit();

                } else {
                    Log.i("Server Token", "failed");
                }
            }
 }

LoginActivity

public class LoginActivity extends AppCompatActivity {

    public static SharedPreferences preferences;
    public static SharedPreferences.Editor editor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        authenticationController = new AuthenticationController();
        preferences = PreferenceManager.getDefaultSharedPreferences(this);
        editor = preferences.edit();
    }

    public void onLoginClicked(View view) {
        getToken();    //FIRST RETROFIT CALL
        connectToPush(); //SECOND CALL WHERE I NEED TOKEN FROM FIRST CALL
    }

    public void getToken() {
        authenticationController.login(grantType, username, password);
    }

    public void connectToPush() {
        authenticationController.connectToPush();
    }

我的第二个 Retrofit 调用
public void connectToPush(){

  Log.i("sharedpreferencesToken", LoginActivity.preferences.getString("serverToken", "null serverToken"));

}

我不熟悉Retrofit,但如果使用AsyncTask,您可以使用AsyncTask.get()来等待结果。https://developer.android.com/reference/android/os/AsyncTask.html#get() - a_m
谢谢您的建议。我正在使用call.enque()(编辑了我的代码),它使用retrofit2异步地进行调用。我不确定我能否在retrofit中实现您建议的内容。 - HappyPoofySquirrel
3个回答

1

onResponse() 方法是一个回调接口,简单来说,它就是你从请求/事件中获取信息的地方(你发起了请求,它回来了,因此称为回调),并实现你想要执行的操作(它是一个接口,你实现它,因此需要 @Override 注释)。

这意味着:

  1. 在这种情况下,你不需要 CountDownLatch,Retrofit2 会为你处理线程。

  2. 没有真正需要使用 SharedPreferences,你可以直接从回调中调用你想要的方法,因为信息就在那个实例中(除非你想为其他目的保存它,见下文...)。

  3. 如果你想要本地存储该值,因为你之后需要使用它(或者以后作为自动登录的东西使用),你可以使用 SharedPreferences,但你不需要在那个实例中从那里获取值 - 因为响应中存在该值(你在那里保存了该值,从 Prefs 中加载它是多余的,而响应中持有确切的值可以简单地传递)。

所以:

call.enqueue(new retrofit2.Callback<TokenResponse>() {    

        @Override
        public void onResponse(Call<TokenResponse> call, retrofit2.Response<TokenResponse> response) {

            if (response.isSuccessful()) {
                TokenResponse tokenResponse = response.body();

                //right here you can call the other request and just give it the token
                connectToPush(tokenResponse);

                //if you really need to, save your value
                LoginActivity.editor.putString("serverToken", tokenResponse.getAccessToken());
                LoginActivity.editor.commit();

            } else {
                Log.i("Server Token", "failed");
            }
        }
 }

在你的第二个调用中:
public void connectToPush(TokenResponse tokenFromFirstRequest){

 //fire the next request using your token as a param!

}

0
你可以在 Retrofit 调用的 onResponse 部分中调用 connectToPush();

0

我最终找到了解决办法。在retrofit的github上找到了答案。
"使用方法1的回调来触发方法2"
我将connectToPush()移到了第一个调用的onResponse中。

  call.enqueue(new retrofit2.Callback<TokenResponse>() {    

            @Override
            public void onResponse(Call<TokenResponse> call, retrofit2.Response<TokenResponse> response) {

                if (response.isSuccessful()) {


               TokenResponse tokenResponse = response.body();

                LoginActivity.editor.putString("serverToken", tokenResponse.getAccessToken());
                LoginActivity.editor.commit();

                connectToPush(); //MOVED TO HERE

            } else {
                Log.i("Server Token", "failed");
            }
        }
 }

随意删除我的问题。我会留下它,因为它可能会帮助其他人


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接