【问题标题】:How to use Retrofit call.enqueue() method (the right way) when dealing with MVP pattern处理MVP模式时如何使用Retrofit call.enqueue()方法(正确方式)
【发布时间】:2019-02-07 12:29:37
【问题描述】:

我是 android 新手,这是第一次尝试在我的代码中使用 MVP 模式......据我所知,到目前为止,我的视图应该与演示者和模型演示者对话 > 然后是演示者将再次谈论查看..我希望我是对的!如下所示,在我的简单代码示例中,我试图从模型返回一个结果值给演示者,然后我将在演示者中使用这个结果值来决定我应该在视图中调用哪个方法..我有 2 个问题我希望有些帮助。 1) enqueue 方法正在异步工作,结果值将始终返回空或失败或其他任何内容.. 因为它单独工作......当我尝试使用 execute 方法时,我面临 NetworkOnMainThreadException 错误......所以我怎样才能做出正确的方法? 2)这是使用MVP模式的正确方法吗?

这是 SignupContract 类

public class SignupContract {
public interface IView{
    void signupSuccess();
    void signupFailed(String message);
}

public interface IPresenter{
    void signup(UserProfile userProfile);
}

public interface IModel{
    String signup(UserProfile userProfile);
}

}
这是查看代码..

public class SignupActivity extends AppCompatActivity implements SignupContract.IView {

//some code

@Override
protected void onCreate(Bundle savedInstanceState) {
    //some code

    createAccountBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

           //some code

            presenter.signup(userProfile);
        }
    });
}

@Override
public void signupSuccess() {
    /*AppUtils.dismissLoadingDialog(SignupActivity.this,"","");*/
    Intent intent = new Intent(SignupActivity.this, SigninActivity.class);
    startActivity(intent);
    finish();
}

@Override
public void signupFailed(String message) {
    /*AppUtils.dismissLoadingDialog(SignupActivity.this,"","");*/
    AppUtils.showErrorMessage(SignupActivity.this, message);
}

这是演讲者

public class SignupPresenter implements SignupContract.IPresenter {

SignupContract.IView view;
SignupContract.IModel model;

public SignupPresenter(SignupContract.IView view){
    model = new SignupModel();
    this.view = view;
}

@Override
public void signup(UserProfile userProfile) {

    userProfile = UserProfileCleaner.clean(userProfile, "signup");

    UserProfileDTO dto = new UserProfileDTO();
    String validationMessage = dto.validateUserProfile(userProfile, "signup");

    if(validationMessage != null && !validationMessage.equals("")){
        view.signupFailed(validationMessage);
    }else{


        String signupResult = model.signup(userProfile);

        if(signupResult.equals("success")){
            view.signupSuccess();
        }else {
            view.signupFailed(signupResult);
        }

    }

}

}

这是模型类

public class SignupModel implements SignupContract.IModel {

private String TAG = "SignupModel";

private String result = "";

@Override
public String signup(UserProfile userProfile) {
    final Context context = DKApp.getContext();
    ServiceWrapper serviceWrapper = new ServiceWrapper(null);
    Call<SignupResponse> userSignUpCall = serviceWrapper.userSignUpCall(userProfile.getUser().getUsername(),
            userProfile.getUser().getPassword(),userProfile.getPhoneNumber(), userProfile.getEmailAddress(),
            userProfile.getFullName());


    userSignUpCall.enqueue(new Callback<SignupResponse>() {
        @Override
        public void onResponse(Call<SignupResponse> call, Response<SignupResponse> response) {
            if( response.body() != null && response.isSuccessful() ){
                Log.e(TAG,response.body().toString());
                if(response.body().getStatus() == 1){
                    //some code
                    result = "success";
                }else{
                    result = response.body().getMessage();
                }
            }else{
                result = context.getResources().getString(R.string.request_failed);
            }
        }

        @Override
        public void onFailure(Call<SignupResponse> call, Throwable t) {
            Log.e(TAG, "Failure : " + t.toString());
            result = context.getResources().getString(R.string.request_failed);
        }
    });

    return result;
}

}

【问题讨论】:

    标签: android retrofit retrofit2 android-mvp


    【解决方案1】:

    您正在模型中进行异步调用,这可能需要 100 毫秒或 2-4 秒,因此像 String signupResult = model.signup(userProfile);this 一样从中获取 signupResult 是错误的。

    您需要的更改:

    1) 将 onComplete 方法添加到 IPresenter 并更改 IModel

    public interface IPresenter{ 
        void signup(UserProfile userProfile);
        //add
        void onComplete(String signUpresult);
    } 
    
    public interface IModel{ 
        //changed
        void signup(UserProfile userProfile);
    } 
    

    2) 在您的 SignupPresenter 中,将演示者的实例传递给模型

    public class SignupPresenter implements SignupContract.IPresenter { 
    ..
    
       public SignupPresenter(SignupContract.IView view){ 
           model = new SignupModel(this); 
           this.view = view;
       } 
    
       ...
    
       @Overrides
       public void onComplete(String signupResult){
          if(signupResult.equals("success")){
            view.signupSuccess(); 
          }else { 
             view.signupFailed(signupResult);
          }
       } 
    
       ...
    }
    

    3) 在您的 SignupModel 中,一旦从演示者那里获取结果调用 onComplete(//result)

    public class SignupModel implements SignupContract.IModel {
    
       SignupPresenter presenter; 
    
       public SignupModel(SignupPresenter presenter){ 
           this.presenter = presenter
       }
    
       @Override 
       public void signup(UserProfile userProfile) {
            ...
            userSignUpCall.enqueue(new Callback<SignupResponse>() {
            @Override 
            public void onResponse(Call<SignupResponse> call, Response<SignupResponse> response) { 
                if(response.body() != null && response.isSuccessful() ){ 
    
                    if(response.body().getStatus() == 1){ 
                        //some code 
                        presenter.onComplete("success"); 
                    }else{ 
                        presenter.onComplete(response.body().getMessage()); 
                    } 
                }else{ 
                    presenter.onComplete(context.getResources().getString(R.string.request_failed)); 
                } 
            } 
    
            @Override 
            public void onFailure(Call<SignupResponse> call, Throwable t) { 
                Log.e(TAG, "Failure : " + t.toString()); 
                presenter.onComplete(context.getResources().getString(R.string.request_failed));  
            } 
        }); 
       }
    
    }
    

    需要:在调用注册时显示进度对话框,并在 SignupPresenter 中的 onComplete 上将其关闭。

    你的理解很好,也知道模型也应该与演示者交谈。要了解有关 MVP 设计模式的更多信息,请阅读this

    【讨论】:

    • 这是一个多么棒的答案......你只是用非常简单明了的线条拯救了世界......非常感谢你的 Suyash Chavan
    【解决方案2】:

    在 MVP 模式中,您应该使视图虚拟化。 Presenter 总是告诉视图该做什么。 这是一个例子:

    在视图中 =>

    presenter.login(userName, password)
    

    在演示者中 =>

    fun login(userName: String, password: String) {
    //login logic
         if(success) view.showLoginSuccess()
         else view.showLoginError()
    }
    

    这是对 MVP 模式的简短说明。关于您的问题,您不能在主线程上提出请求。幸运的是 Retrofit 有一个线程管理系统。但是您不应该在这样的模型中使用它,您可以在演示者中使用它或搜索干净的架构文章以获得更正确的方式。如果你在presenter中使用它,你应该做类似的事情

    userSignUpCall.enqueue(new Callback<SignupResponse>() {
            @Override
            public void onResponse(Call<SignupResponse> call, Response<SignupResponse> response) {
                if( response.body() != null && response.isSuccessful() ){
                    Log.e(TAG,response.body().toString());
                    if(response.body().getStatus() == 1){
                        //some code
                        view.showMessage("success");
                    }else{
                        view.showMessage(response.body().getMessage());
                    }
                }else{
                    view.showError(context.getResources().getString(R.string.request_failed));
                }
            }
    
            @Override
            public void onFailure(Call<SignupResponse> call, Throwable t) {
                Log.e(TAG, "Failure : " + t.toString());
                view.showError(context.getResources().getString(R.string.request_failed));
            }
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多