如何使用Retrofit和RxJa处理两个JSON响应?

时间:2017-01-04 18:14:16

标签: android rx-java retrofit2 rx-android

我正在向服务器发送API请求,我可以获得两个JSON响应:

  • 经过身份验证的用户的JSON响应
  • 未经身份验证的用户的JSON响应

经过身份验证的用户响应:

{"status":"ok","tekst":"8bc6c9cf-293f-11e5-9940-448a5b5dd2bd","requestID":9034}

未经身份验证的用户响应:

{"authenticationError":"User authentication failed"}

改造服务:

public interface LiveService {
    @GET("live.php")
    Observable<Response<LiveResponse>> getLive();
}

这是对服务器的改造请求:

retrofit.create(LiveService.class)
            .getLive()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Response<LiveResponse>>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    liveView.onLiveError(e);
                }

                @Override
                public void onNext(Response<LiveResponse> response) {


                }
            });

如何在onNext中处理响应,以检查我是否为经过身份验证的用户或未经身份验证的用户提供JSON响应?

3 个答案:

答案 0 :(得分:4)

您的模型需要将两者的所有字段合并为一个POJO。那很简单: - )

不存在的经过身份验证的用户/未经身份验证的用户将只为null。

更清楚......

让我们做两个不同的回复。以下是我遇到的两个随机JSON有效负载。

@Override
protected void onCreate(Bundle savedInstanceState) {
    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    layout = (RelativeLayout) findViewById(R.id.activity_main);
    Point size = new Point();
    Display display = getWindowManager().getDefaultDisplay();
    display.getRealSize(size);
    params = new RelativeLayout.LayoutParams(size.x / 5, 200);
    padding = size.x / 5;
    addButtons();
}

public void addButtons() {
    Button update = new Button(this);
    RelativeLayout.LayoutParams updateParams = params;
    updateParams.addRule(RelativeLayout.CENTER_VERTICAL);
    update.setLayoutParams(updateParams);
    update.setPadding(padding, 0, 0, 0);
    update.setText("Update Me!");
    update.setOnClickListener(new ClickHandler("app_update"));
    updateId = update.generateViewId();
    update.setId(updateId);
    layout.addView(update);

    Button install = new Button(this);
    RelativeLayout.LayoutParams installParams = params;
    installParams.addRule(RelativeLayout.RIGHT_OF, update.getId());
    installParams.addRule(RelativeLayout.CENTER_VERTICAL);
    install.setLayoutParams(installParams);
    install.setPadding(padding, 0, 0, 0);
    install.setText("Install LastBox");
    install.setOnClickListener(new ClickHandler("kodi_install"));
    installId = install.generateViewId();
    install.setId(installId);
    layout.addView(install);

    Button dlFamily = new Button(this);
    RelativeLayout.LayoutParams dlFamilyParams = params;
    dlFamilyParams.addRule(RelativeLayout.RIGHT_OF, install.getId());
    dlFamilyParams.addRule(RelativeLayout.ABOVE, install.getId());
    dlFamily.setLayoutParams(dlFamilyParams);
    dlFamily.setPadding(padding, 0, 0, padding);
    dlFamily.setText("Download Family Build");
    dlFamily.setOnClickListener(new ClickHandler("family_download"));
    dlFamilyId = dlFamily.generateViewId();
    dlFamily.setId(dlFamilyId);
    layout.addView(dlFamily);

    Button upFamily = new Button(this);
    RelativeLayout.LayoutParams upFamilyParams = params;
    upFamilyParams.addRule(RelativeLayout.RIGHT_OF, install.getId());
    upFamilyParams.addRule(RelativeLayout.BELOW, install.getId());
    upFamily.setLayoutParams(upFamilyParams);
    upFamily.setPadding(padding, padding, 0, 0);
    upFamily.setText("Update Family Build");
    upFamily.setOnClickListener(new ClickHandler("family_update"));
    upFamilyId = upFamily.generateViewId();
    upFamily.setId(upFamilyId);
    layout.addView(upFamily);

    Button dlAdult = new Button(this);
    RelativeLayout.LayoutParams dlAdultParams = params;
    dlAdultParams.addRule(RelativeLayout.RIGHT_OF, dlFamily.getId());
    dlAdultParams.addRule(RelativeLayout.ABOVE, install.getId());
    dlAdult.setLayoutParams(dlAdultParams);
    dlAdult.setPadding(padding, 0, 0, padding);
    dlAdult.setText("Download Adult Build");
    dlAdult.setOnClickListener(new ClickHandler("adult_download"));
    dlAdultId = dlAdult.generateViewId();
    dlAdult.setId(dlAdultId);
    layout.addView(dlAdult);

    Button upAdult = new Button(this);
    RelativeLayout.LayoutParams upAdultParams = params;
    upAdultParams.addRule(RelativeLayout.RIGHT_OF, upFamily.getId());
    upAdultParams.addRule(RelativeLayout.BELOW, install.getId());
    upAdult.setLayoutParams(upAdultParams);
    upAdult.setPadding(padding, padding, 0, 0);
    upAdult.setText("Update Adult Build");
    upAdult.setOnClickListener(new ClickHandler("adult_update"));
    upAdultId = upAdult.generateViewId();
    upAdult.setId(upAdultId);
    layout.addView(upAdult);
}

引导我们找到像

这样的组合对象
   {
        "title": "Sample Konfabulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    }



   { 
        "src": "Images/Sun.png",
        "name": "sun1",
        "hOffset": 250,
        "vOffset": 250,
        "alignment": "center"
    }

给我们一个看起来像这样的POJO。

    {
    "title": "Sample Konfabulator Widget",
    "name": "main_window",
    "width": 500,
    "height": 500,
    "src": "ImagesSun.png",
    "hOffset": 250,
    "vOffset": 250,
    "alignment": "center"
   }

答案 1 :(得分:3)

我同意StarWind,添加另一个字段将帮助您稍后决定如何处理响应,但首先您需要调整您的方法,其中最终结果不是Response<T>,而是身体(对象)。通过以下列方式链接调用,可以使用RxJava轻松完成此操作:接收响应,检查是否成功,检查反序列化的正文对象是否包含身份验证错误字段。

retrofit.create(LiveService.class).getLive().flatMap(new Function<Response<LiveResponse>, ObservableSource<LiveResponse>>() {
            @Override
            public ObservableSource<LiveResponse> apply(Response<LiveResponse> liveResponse) throws Exception {
                LiveResponse body =  liveResponse.body();
                if(liveResponse.isSuccessful() && body != null && body.getAuthenticationError() == null){ //probably check http error code too
                    return Observable.just(body);
                }else if(body != null){
                    throw new AuthenticationException(body.getAuthenticationError());
                }else{
                 throw IllegalArgumentException("something terribly happened here"); }
            }
        }).subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<LiveResponse>() {
                @Override
                public void onComplete() {

                }

                @Override
                public void onError(Throwable e) {
                    liveView.onLiveError(e); //authentication error maybe or network excp
                }

                @Override
                public void onNext(LiveResponse body) {


                }
            });

请注意,我使用了RxJava 2,但您可以在RxJava 1中轻松地重写它。

答案 2 :(得分:2)

改造只能处理一种数据类型。也许你可以使用authenticated_user&amp;创建主用户对象。 unauthenticated_user对象。也许您应该要求后端团队返回布尔值或任何变量来识别数据类型。

class User {
AuthUser authUser;
UnAuthUser unAuthUSer;
}