android - 在处理 MVP 模式时如何使用 Retrofit call.enqueue() 方法(正确的方法)

标签 android retrofit retrofit2 android-mvp

我是 android 的新手,这是我第一次尝试在我的代码中使用 MVP 模式......据我所知,我的 View 应该与演示者交谈,然后是演示者与模型 > 然后是演示者将再次讨论以查看..我希望我是对的!如下图所示,在我的简单代码示例中,我试图将模型的结果值返回给演示者,然后我将在演示者中使用该结果值来决定我应该在 View 中调用哪个方法。我有 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;
}

最佳答案

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

您需要进行的更改:

1) 给IPresenter添加onComplete方法并改变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

关于android - 在处理 MVP 模式时如何使用 Retrofit call.enqueue() 方法(正确的方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54573368/

相关文章:

android - DeviceAdmin 策略 PASSWORD_QUALITY_NUMERIC 不起作用

java - 无法解析 fragment 中微调器适配器的构造函数

android - Retrofit 2 调用失败 - 抽象方法 "void okhttp3.Callback.onResponse"

android - 如何让build.gradle支持多国语言?

java - Android 适配器上下文

java - 执行同步 PUT 请求时改造中的 EOFException

android - 如何使用 Retrofit 添加 TLS v 1.0 和 TLS v.1.1

java - 使用 Gson 和改造的 Java 的 Json 错误 [预期为 BEGIN_ARRAY,但在第 1 行第 70 列路径 $.Data 处为 BEGIN_OBJECT]

安卓 RxJava : Chaining two requests and doing some logic inbetween

android - 如何在没有丑陋的 instanceof 的情况下处理 Retrofit Rx onError 中的不同类型的错误