android MVP 开发模式

android MVP 开发模式的理解

       在进入MVP介绍前。我们先来看一下一直沿用的MVC的开发的模式。


       明人一看上面的结构图就知道MVC中是允许Model 和 View  进行交互的。

每种模式都有利与弊,不能说那种模式好与不好。为了“高内聚,低耦合”的思想。个人觉得MVP更能体现之特性。

下面让我们来看看MVP的结构图:


   View对应于activity,负责View的绘制以及用户的交互,理应做到View是最薄的一层,利于UI重新设计与变更。
     Model 数据源与实体模型。比如,保存到本地的数据。数据库的数据。网络请求回来的数据。
     Presenter 负责View与Model的交互。起到一个中间的角色。说白了就是个控制器。由它来控UI的数据来源和UI显示。

  • 如果理解这三个概念。接下来就说说代码结构吧。

代码分块。这并不是MVP的主旨。可以根据个人爱好来分。最重要的是我们在写代码时,如何运用MVP的思维。做到代码清淅明了,维护性高。逻辑简单明了。

接下来看一个简单的例子。如


/**
 * Created by cc on 16/4/13.
 */
public interface ILoginView {

    String getPhone();

    String getPassWord();

    void setPhone(String phone);

    void setPassWroid(String passWroid);

    void startIndexActivity();

    void startForgetActivity();

    Context getContext();

    void promptToastMessge(String msg);



    void showProgressBar(String msg);

    void setProgressBarMessage(String msg);

    void hideProgressBar();


}

/**
 * Created by cc on 16/4/13.
 */
public interface ILoginMode {

    void onSuccess(Object object);

    void onFail(Object object);
}
/**
 * Created by cc on 16/4/13.
 */
public class LoginService {


    public LoginService(final ILoginMode iLoginMode) {

        //这里模拟网络请求。按道理来说。这里不该出现os包的代码。这里只为了测试。
        // 建设 model层。放在异步线程执行。可以试一下
        //Rx(rxjava或rxandroid) 与 Retrogit
        //Rx(rxjava或rxandroid) 可以简单理解为"异步"
        //Retrogit网络请求

       new Handler().postDelayed(new Runnable() {
           @Override
           public void run() {
               //模拟加载数据

               if (new Random().nextBoolean()){
                   iLoginMode.onSuccess("请求成功");
                   return;
               }
               iLoginMode.onFail("请求失败");
           }
       },3000);




    }
}

/**
 * Created by cc on 16/4/13.
 */
public class LoginPresenter {

    private ILoginView mILoginView;


    public LoginPresenter(ILoginView iLoginView) {
        mILoginView = iLoginView;
    }

    public void onCreate() {

        LocalLoginPhone localLoginPhone = new LocalLoginPhone();

        String phone = localLoginPhone.getLoginPhone(mILoginView.getContext());

        mILoginView.setPhone(phone);

    }

    public void deletePhoneClick() {

        mILoginView.setPhone("");

    }

    public void deletePassWordClick() {
        mILoginView.setPassWroid("");
    }

    public void forgetPassWordClick() {
        mILoginView.startForgetActivity();
    }

    public void LoginClick() {

        String phone = mILoginView.getPhone();

        if (TextUtils.isEmpty(phone)) {

            mILoginView.promptToastMessge("填写信息有误");

            return;
        }

        String possWord = mILoginView.getPassWord();

        if (TextUtils.isEmpty(possWord)) {

            mILoginView.promptToastMessge("填写信息有误");

            return;
        }

        mILoginView.showProgressBar("正在加载");

        LoginService loginService = new LoginService(new ILoginMode() {
            @Override
            public void onSuccess(Object object) {
                mILoginView.setProgressBarMessage(object.toString());
                mILoginView.hideProgressBar();

                mILoginView.startIndexActivity();
            }

            @Override
            public void onFail(Object object) {
                mILoginView.setProgressBarMessage(object.toString());
                mILoginView.hideProgressBar();
                mILoginView.promptToastMessge("提交失败");
            }
        });


    }


}

/**
 * Created by cc on 16/4/13.
 */
public class LogInActivity extends BaseActivity implements ILoginView {


    private EditText login_et_phone, login_et_password;

    private Button login_btn_delete_phone, login_btn_delete_password, login_btn_login, login_btn_forget_password;

    private LoginPresenter mLoginPresenter;

    private LittleDialog mDialog;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.act_login);

        initView();

        mLoginPresenter = new LoginPresenter(this);
        mLoginPresenter.onCreate();
    }



    private void initView() {

        login_et_phone = (EditText) findViewById(R.id.login_et_phone);
        login_et_password = (EditText) findViewById(R.id.login_et_password);
        login_btn_delete_phone = (Button) findViewById(R.id.login_btn_delete_phone);
        login_btn_delete_password = (Button) findViewById(R.id.login_btn_delete_password);
        login_btn_login = (Button) findViewById(R.id.login_btn_login);
        login_btn_forget_password = (Button) findViewById(R.id.login_btn_forget_password);


        login_btn_delete_phone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mLoginPresenter.deletePhoneClick();
            }
        });
        login_btn_delete_password.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mLoginPresenter.deletePassWordClick();
            }
        });
        login_btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mLoginPresenter.LoginClick();
            }
        });
        login_btn_forget_password.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mLoginPresenter.forgetPassWordClick();
            }
        });

    }

    @Override
    public String getPhone() {
        return login_et_phone.getText().toString().trim();
    }

    @Override
    public String getPassWord() {
        return login_et_password.getText().toString().trim();
    }

    @Override
    public void setPhone(String phone) {

        login_et_phone.setText(phone);

    }

    @Override
    public void setPassWroid(String passWroid) {
        login_et_password.setText(passWroid);
    }

    @Override
    public void startIndexActivity() {
        UIHelper.startActivity(this, IndexActivity.class, null);
    }

    @Override
    public void startForgetActivity() {

    }

    @Override
    public Context getContext() {
        return this;
    }

    @Override
    public void promptToastMessge(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }


    @Override
    public void showProgressBar(String msg) {
        mDialog = new LittleDialog(this, msg);
        mDialog.show();

    }

    @Override
    public void setProgressBarMessage(String msg) {
        if (null != mDialog)
            mDialog.setMessage(msg);
    }

    @Override
    public void hideProgressBar() {

        if (null != mDialog)
            mDialog.dismiss();

    }


}

/**
 * UI操作辅助类
 * @author alafighting 2016-0
 */
public class UIHelper {

    /**
     * 界面跳转
     * @param context
     * @param activity
     * @param bundle
     */
    public static void startActivity(Context context, Class<? extends Activity> activity, Bundle  bundle) {
        if (context == null) {
            throw new NullPointerException("context不能为空");
        }
        Intent intent = new Intent(context, activity);

        if (null !=bundle){
            intent.putExtras(bundle);
        }


        context.startActivity(intent);
    }


    /**
     * 打开主界面
     * @param context
     */
    public static void startMain(Context context) {
        startActivity(context, IndexActivity.class,null);
    }

}

/**
 * Created by cc on 16/4/13.
 */
public class BaseActivity extends AppCompatActivity {


    public Context getContext() {
        return super.getApplicationContext();
    }

    public Activity getActivity() {
        return this;
    }

    public <T extends android.support.v4.app.Fragment> T findSupportFragment(Class<T> fragmentClass) {
        android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
        android.support.v4.app.Fragment fragment = fragmentManager.findFragmentByTag(fragmentClass.getName());
        return (T) fragment;
    }

    public <T extends android.support.v4.app.Fragment> T newSupportFragment(Class<T> fragmentClass, Bundle args) {
        android.support.v4.app.Fragment fragment = android.support.v4.app.Fragment.instantiate(getContext(), fragmentClass.getName(), args);
        fragment.setArguments(args);
        return (T) fragment;
    }
}

上面的例子是不是看起来很明了。关键问题,大家看到这代码后,会认为这只是把逻辑代码模块的东西放到一另一个类而已。如果你这么理解。说明你对写代码的一个整体认识观不是很有艺术。人人都说写代码是一门艺术。

上面的代码结构还是有好处的。如,当测试跟你说这接口请求出错了。出bug了。这时平常我们会去找到这个接口在那个activity里调用。在那一行代码里。聪明的人可能不会这么干。或许习惯自已写测试用例时,只需调用LoginService实现ILoginModel接口就好了,就可以知道自已有没有搞错了。是不是很 66666

最后说一个mvp 的优点

MVP的优点:

模型与视图完全分离,我们可以修改视图而不影响模型

可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部

我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非    常的有用,因为视图的变化总是比模型的变化频繁。

如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单    元测试)


说明。上面有一两张图是截网上的。如果有侵权,请及时联系我删除,谢谢。

在此感谢以上几个人。老八,壳,替补,roy,朽木,在我理解MVP 过程中。他们给予我解答



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章