1

我实现了网络调用来验证登录,它工作正常。登录成功后,我在再次调用以获取用户数据时遇到了一些麻烦。

这是 API 调用:

RestApi restApi = ServiceRest.createRetrofitService(RestApi.class, UrlServer.URL_SERVER);
Observable<Response<User>> responseObservable = restApi.getUser(user);
responseObservable.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .unsubscribeOn(Schedulers.io())
        .subscribe(new Subscriber<Response<User>>() {
            @Override
            public void onCompleted() {
                Log.i("LoginActivity", "[onCompleted]");
                progressDialog.dismiss();
            }

            @Override
            public void onError(Throwable e) {
                progressDialog.dismiss();
                Toast.makeText(LoginActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNext(Response<User> userResponse) {
                //Do stuff to go to another Activity
            }
        });


------------- 编辑#1 -------------

我实现了@Tassos 的建议,如下所示:

responseUser
         .subscribeOn(Schedulers.io())
         .observeOn(AndroidSchedulers.mainThread())
         .map(new Func1<Response<User>, Observable<Response<Object>>>() {
                 @Override
                 public Observable<Response<Object>> call(Response<User> userResponse) {
                     Log.d("USER", userResponse.body().getName());
                     return restApi.getData(userResponse.body().getToken());
                 }
            })
            .doOnError(new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    Toast.makeText(LoginActivity.this, "Error[doOnError]: " + throwable.toString(), Toast.LENGTH_SHORT).show();
                }
            })
            .subscribe(new Subscriber<Object>() {
                @Override
                public void onCompleted() {
                    Log.i("LoginActivity", "[onCompleted]");
                }
                @Override
                public void onError(Throwable e) {
                    Toast.makeText(LoginActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
                @Override
                public void onNext(Object result) {
                    Log.d("RESPONSE", result.toString());
                }
            });

在订阅方法上这样做是否正确?我需要转换 onNext 的 Object 结果吗?

//------------------------------------------------ ---------------------------------------//

我想在登录成功后,使用通过响应对象 User 获得的令牌调用另一个 url,并将其Observable<Response<Object>> getData(@Header("Authorization") String token);作为 Header 的授权发送到另一个 api 调用()。我曾尝试使用 flatMap 和 zip,但我无法完成这项任务。
有什么建议吗?这个概念对我来说是新的。

4

2 回答 2

4

操作员是进行一次 API 调用然后进行另一次调用的.flatMap完美方式。在这里阅读:http ://blog.danlew.net/2014/09/22/grokking-rxjava-part-2/ “它变得更好”部分。

.flatMap允许您将一个 observable 更改为另一个 observable,即使用前一个的结果进行新的 API 调用,实现事件链。如果你这样做,订阅者将被调用来获取一个从.flatMap.

你只需写:

restApi.getUser(user)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .flatMap(userResponse -> restApi.getData(userResponse.getToken()))
    .doOnError(e -> Toast.makeText(LoginActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show())
    .doOnTerminate(() -> progressDialog.dismiss())
    .subscribe(response -> proceedWithLogin())

还有你为什么用.unsubscribeOn(Schedulers.io())?当你使用改造 observables 时,它们通常会生成一个事件,然后完成,并且不需要设置取消订阅调度程序。

于 2016-06-18T10:37:45.063 回答
3

那么,你真的需要用户关闭对话框吗?在进行其他通话之前,您绝对需要关闭对话框吗?

    .unsubscribeOn(Schedulers.io())
    .map(userResponse -> { /* do the other calls */ }
    .subscribe(new Subscriber<?>() {...
于 2016-06-18T09:36:45.477 回答