使用 RXJava 和 Retrofit 的网络调用正确实现 - Android

Network call with RXJava and Retrofit correct implementation - Android

我想对用户端点进行简单的 api 调用(注册新用户)并通过响应获取身份验证令牌。任何人都可以解释这两个网络调用之间的区别以及在我的情况下哪种实现是正确的?

 private void registerProcess(User user) {
    mSubscriptions.add(Network.getRetrofit().getUserToken(user)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<Response<TokenResponse>>() {
                @Override
                public void call(Response<TokenResponse> tokenResponse) {
                    if (tokenResponse.code() == 200) {
                        mProgressbar.setVisibility(View.GONE);
                        showSnackBarMessage("Registration success!");
                    } else {
                        mProgressbar.setVisibility(View.GONE);
                        showSnackBarMessage("Registration failed");
                    }

                }
            }));

}

 private void registerProcess(User user) {

    Network.getRetrofit().getUserToken(user)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Response<TokenResponse>>() {
                @Override
                public void onCompleted() {
                    /// what to do here???
                }

                @Override
                public void onError(Throwable e) {
                    mProgressbar.setVisibility(View.GONE);
                    showSnackBarMessage("Registration failed");
                }

                @Override
                public void onNext(Response<TokenResponse> tokenResponse) {
                  if (tokenResponse.code() == 200) {
                        mProgressbar.setVisibility(View.GONE);
                        showSnackBarMessage("Registration success!");
                    } 
                }
            });

}

第一种情况:

  • 没有 onError 回调处理,因此,例如 IOException 会使您的应用程序崩溃。

第二个:

  • 订阅不会存储在任何地方(与第一种情况不同),因此如果它仍然是 运行 并且没有在 activity 的 onDestroy 回调中取消订阅,它将泄漏。
  • onNext 仅处理成功的响应,因此如果 HTTP 代码不同于 200,则不会发生任何事情。

正确的实现是融合这两个片段:

private void registerProcess(User user) {
    mSubscriptions.add(Network.getRetrofit().getUserToken(user)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<Response<TokenResponse>>() {
            @Override
            public void onCompleted() {
                // you might do nothing here
            }

            @Override
            public void onError(Throwable e) {
                mProgressbar.setVisibility(View.GONE);
                showSnackBarMessage("Error!");
            }

            @Override
            public void onNext(Response<TokenResponse> tokenResponse) {
                if (tokenResponse.code() == 200) {
                    mProgressbar.setVisibility(View.GONE);
                    showSnackBarMessage("Registration success!");
                } else {
                    mProgressbar.setVisibility(View.GONE);
                    showSnackBarMessage("Registration failed");
                } 
            }
        });
}

不要忘记在 activity(或片段)被销毁时调用 mSubscriptions.clear(),以取消订阅所有已存储的订阅。

P.S. 您可以利用 doOnSubscribedoAfterTerminate 运算符来相应地设置初始和终端视图状态。例如,避免多次调用 mProgressbar.setVisibility(View.GONE):

mSubscriptions.add(Network.getRetrofit().getUserToken(user)
    .doOnSubscribe(() -> mProgressbar.setVisibility(View.VISIBLE))
    .doAfterterminate(() -> mProgressbar.setVisibility(View.GONE))
    ...