认识GOOGLE官方架构MVP

认识GOOGLE官方架构MVP

  • MVP框架简述
  • MVP框架分析
  • 实战示范
  • 参考内容

MVP框架简述

MVP由model–view–controller (MVC)软件模式衍生而来,是一个把view从底层分离出来的一种轻量模型。
M(model)代表的是将会显示在view(UI)中的数据。
V(view)是显示数据(model)并且将用户指令(events)传送到presenter以便作用于那些数据的一个接口。View通常含有Presenter的引用。
P(presenter)起到控制的作用,是一个中转元素(如 MVC中的controller),且presenter同时引用view和model。
MVP架构

MVP框架分析

  • Presenter解耦
    Presenter起到的就是转发和控制的作用,如果采用传统的OnClickListener监听来代替Presenter,则无法对View内部元素进行合理的控制,控制逻辑复杂。而Presenter了解View的内部结构,可以有效地进行控制,并保证低耦合。
    加之,Presenter不应被绑定到Android平台,Presenter的内容应该是普遍意义上能与其他任何java应用共享的java代码。
  • View自主权
    View只执行Presenter指示的操作,即完全依靠Presenter的控制进行工作,所以在进行接口设计时,应该让Presenter控制View的方式更加抽象,粒度不能够太小。
类图及分析如下

MVP类图
- BaseView
界面需要提供的方法中会有很多类似的,把它们提取到一个公共的父类接口中。比如setPresenter方法,其他的view层接口就可以直接继承BaseView接口,不必做重复工作。

public interface BaseView<T> {
    void setPresenter(T presenter);
}
  • BasePresenter
    同理,BasePresenter提供重复的Presenter接口。
public interface BasePresenter {
    void start();
}
  • Contract
    工程中,每一个模块都有一个自己的Contract接口,Contract包涵了Presenter和View,Presenter实现的逻辑层方法,View实现的界面层的方法都能在Contract接口中一目了然的看明白,具体的Presenter和View的实现类都是通过实现Contract接口来完成。这种管理办法使得开发和维护十分简单。
public interface XXXContract {    
    interface View extends BaseView<Presenter> {  
    }      
}     
    interface Presenter extends BasePresenter {         
    }
}

实战示范

  • 项目目录
    注:实例来自笔者亲身参与的一款运动体验项目
    项目结构的组织方式基本按照功能进行划分,之后我们具体关注login模块中MVP的实现用于理解MVP的实现流程。
    项目目录

    login模块

  • LoginContract
    具体login任务的Presener和View接口,Presenter接口里面封装的是数据获取的方法,需要数据提供者具体实现;View里面封装是界面层(Fragment)要实现的方法。
public interface LoginContract {
    interface View extends BaseView<Presenter> {
        /**
         * 设置加载提示符
         */
        void showLoadingIndicator();
        /**
         * 设置出错信息
         */
        void showErrorInfo();
    }

    interface Presenter extends BasePresenter {
        boolean checkAccount(String username, String password);
    }
}
  • LoginPresenter
    继承LoginContract.Presenter接口,实现具体的功能方法,代码不再赘述。
  • LoginActivity
    在MVP架构中,个人理解Activity主要负责控制,Fragment负责展示,当然MVP只是一种思想,代码书写的方式因人而异。
    LoginActivity的主要只能有初始化Fragment并创建Presenter。
public class LoginActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login_act);
        LoginFragment loginFragment = (LoginFragment) getSupportFragmentManager().findFragmentById(R.id.layout_login_content);

        if (loginFragment == null) {
            loginFragment = loginFragment.newInstance();         ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), loginFragment, R.id.layout_login_content);
        }
        new LoginPresenter(loginFragment);
    }
}
  • LoginFragment
    LoginFragment是View接口的实现类,其不与Model层进行交互,只和presenter的实例进行交互。
    LoginFragment持有相应LoginPresenter的引用,通过view的setPresenter方法完成实例的关联操作。当LoginFragment收到界面操作请求即通过LoginPresenter完成逻辑上的处理。
public class LoginFragment extends Fragment implements LoginContract.View {

    private LoginContract.Presenter mPresenter;

    private EditText edtTxt_userName;

    private EditText edtTxt_passWord;

    private Button btn_login;

    private Button btn_noAccount;

    public static LoginFragment newInstance() {
        return new LoginFragment();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.login_frag, container, false);
        return root;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        btn_login = (Button) getActivity().findViewById(R.id.btn_login);

        btn_noAccount = (Button) getActivity().findViewById(R.id.btn_noAccount);

        edtTxt_userName = (EditText) getActivity().findViewById(R.id.edtTxt_userName);

        edtTxt_passWord = (EditText) getActivity().findViewById(R.id.edtTxt_passWord);

        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean loginResult = mPresenter.checkAccount(edtTxt_userName.getText().toString(), edtTxt_passWord.getText().toString());
                if (loginResult) {
                    getActivity().finish();
                    Intent intent = new Intent(getActivity(), HomePageActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    startActivity(intent);
                }

            }
        });

        btn_noAccount.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getActivity(), RegisterActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        mPresenter.start();
    }

    @Override
    public void onStop() {
        super.onStop();
        edtTxt_userName.setText("");
        edtTxt_passWord.setText("");
    }

    @Override
    public void showLoadingIndicator() {
        Toast.makeText(getActivity().getApplicationContext(), "登录成功",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showErrorInfo() {
        Toast.makeText(getActivity().getApplicationContext(), "用户名或密码错误",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setPresenter(LoginContract.Presenter presenter) {
        mPresenter = presenter;
    }
}

参考内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值