使用存储库模式在 MVP 中捕获响应 return

catch the response return in MVP with repository pattern

我遇到了问题:我一直在创建一个将 return 响应的登录过程。如果登录为真,它会给出这样的响应。

{   
    "error": false,   "message": "Logged In Successfully",   
    "user": {
        "username": "administrator",
        "email": "admin@admin.com",
        "first_name": "USER",
        "last_name": "ADMIN"   
    },   
    "menu": [
       {
         "name": "MENU A",
         "module": "menu_a",
         "controller": "",
         "parent_module": "",
         "status": ""
       },
       {
          "name": "MENU B",
          "module": "menu_b",
          "controller": " ",
          "parent_module": "",
          "status": ""
       }   
    ],   
    "privilege": [
       {
           "module": "menu_a"
       },
       {
           "module": "menu_b"
       }   
    ] 
}

然后当它为假时,它会return这样的响应。

{   "error": true,   "message": "Incorrect Login",   "user": {
    "username": "none",
    "email": "none",
    "first_name": "none",
    "last_name": "none",
    "company": "none",
    "phone": "none",
    "gender": "none",
    "place_of_birth": "none",
    "date_of_birth": "none",
    "religion": "none",
    "photo": "none"   },   "menu": "none",   "privilege": "none" }

这是我的代码:

public interface AppDataSource {   

     Single<LoginResponse> attemptLogin(Login login);

     Single<LoginResponse> saveUserData(LoginResponse response);

}

public class AppRemoteDataSource implements AppDataSource {

    private final Retrofit retrofit;

    @Inject
    public AppRemoteDataSource(@NonNull Retrofit retrofit) {
        this.retrofit = retrofit;
    }

    @Override
    public Single<LoginResponse> attemptLogin(Login login) {
        return retrofit.create(OmrService.class).loginUser(login);
    }

    @Override
    public Single<Boolean> checkLogin() {
        throw new UnsupportedOperationException();
    }
}

public class AppLocalDataSource implements AppDataSource {

    @NonNull
    private final SharedPreferences sharedPreferences;

    @NonNull
    private final Realm realm;

    @Inject
    public AppLocalDataSource(@NonNull SharedPreferences sharedPreferences, @NonNull Realm realm) {
        this.sharedPreferences = sharedPreferences;
        this.realm = realm;
    }
    @Override
    public Single<Boolean> checkLogin() {
       return Single.create(s -> {
           Boolean stsLogin = sharedPreferences.getBoolean("IS_USER_LOGIN", >false);
           s.onSuccess(stsLogin);
       });
    }
    @Override
    public Single<LoginResponse> saveUserData(LoginResponse response) {
       return Single.create(e -> {
           if(!response.isError()) {
               savePreference(response.getUser());
               saveMenuPrivilege(response.getMenu(), >response.getPrivilege());
           }
           e.onSuccess(response);
       });
    }

}

public class AppRepository implements AppDataSource {

    @NonNull
    private final AppDataSource localDataSource;

    @NonNull
    private final AppDataSource remoteDataSource;

    @Inject
    public AppRepository(@NonNull @Local AppDataSource localDataSource,
                         @NonNull @Remote AppDataSource remoteDataSource) {
        this.localDataSource = localDataSource;
        this.remoteDataSource = remoteDataSource;
    }

    @Override
    public Single<LoginResponse> attemptLogin(Login login) {
        return remoteDataSource.attemptLogin(login)
                .compose(RxUtils.applySingleSchedulers())
                .flatMap(localDataSource::saveUserData);
    }

    @Override
    public Single<Boolean> checkLogin() {
        return localDataSource.checkLogin();
    }

}

public class LoginPresenter implements LoginContract.Presenter {


    private LoginContract.View view;

    private CompositeDisposable compositeDisposable = new CompositeDisposable();

    private AppRepository repository;


    @Inject
    public LoginPresenter(AppRepository repository, LoginContract.View view) {
        this.repository = repository;
        this.view = view;

    }

    private void attemptLogin(Login login) {
        view.showProgressIndicator(true);
        compositeDisposable.add(repository.attemptLogin(login)
                .subscribe(
                        response -> {
                            if(response.isError()) {
                                Log.d("CHECK RESPONSE ", response.getMessage());
                                view.makeSnack(response.getMessage().toString().replace("<p>","").replace("</p>",""));
                            } else {
                                view.showProgressIndicator(false);
                                view.startMainActivity();
                            }
                        } , e -> {
                            Log.d("CHECK RESPONSE ERROR", e.getMessage());
                            view.makeSnack(e.getMessage().toString());
                            view.showProgressIndicator(false);
                        }
                ));
    }
}

问题是,当我测试错误的用户名时,Toast 中显示的响应不是 "Incorrect Login",而是 "com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 268 path $.menu"

我知道登录为假时菜单和权限是空的。但是我如何才能捕捉到响应消息 "Incorrect login"?有没有我需要更改的代码部分?

提前致谢

问题出在您的 privilege 密钥上。

成功后它是一个数组:"privilege": [ { "module": "menu_a" }, { "module": "menu_b" } ]

失败是一个字符串:"privilege":"none"

使其工作的一个简单方法是将 "none" 更改为 []

问题出在您的 JSON 反序列化器(GSON?)中,它显然不能以相同的方式表示字符串和数组。

因此,如果您无法更改服务器响应,您很可能需要创建一个可以为您进行转换的自定义反序列化程序。如何做到这一点取决于用于将 JSON 转换为 Java.

的内容