MVP的实践

来源:互联网 发布:淘宝怎么刷単赚钱 编辑:程序博客网 时间:2024/05/22 06:55

背景:

之前看到有朋友在项目中用mvp模式,他推荐我去看看google托管在github上的一个demo,然后我就下载下来看,结果是看得稀里糊涂的,感觉几个接口调来调去的,让我不够用的大脑更加混乱了。然后,我又在网上搜索一些文章看,结果绝大部分文章标题是:Retrofit+RxJava+Dragger2+MVP模式,一下子包装这么多框架进去,更是让看了之后,更是不会了。后面自己想:既然整体看不懂,为什么不一个一个的看呢?那就先只看纯MVP的demo,后面的Retrofit,RxJava, Dragger2排队一个一个来学习好了。在化繁为简的轻情况下,终于对MVP有所理解,下面我讲解下自己当时学习的过程,一是加深自己的理解,二是希望别人也能容易看懂。我会便用2个例子来构建,见如下结构:

这里写图片描述

案例一:

在MainActivty里面做用户登录的操作:

view: IUserLoginView MainActivity

module: IUser(接口), IUserImpl(接口的实现类)OnLoginListener(登录结果的回调)

presenter: UserLoginPresenter

1.先说module层要写些什么:大家对这个可能有点疑惑,因为我当初也是不知道这个moudle到底该写些什么好,只知道概念上说:业务逻辑在这里做。后面思索:在没有MVP的时候,我们要从网络上获取数据,或是将用户数据传递给服务端,不就是具体的业务逻辑吗?只不过以前是写在一个类中,现在将其划分给module就好了。以注册和登录为例,我们要将用户数据交给服务端,那么,我猜想你应该知道要怎么写了,参考如下:

public interface  IUser {   void  login(String name,String psw,OnLoginListener loginListener);}/** * 登录的具体业务类 */public class IUserImpl implements IUser{    @Override    public void login(String name, String psw, OnLoginListener loginListener) {            if("123".equals(name)&&"123".equals(psw)){                User user = new User(name,psw);                loginListener.onloginSucced(user);            }else{                loginListener.onloginFailed();            }    }}

2.再来看view层怎么写:看这个的时候,又难倒我了,再次回想没有MVP的时候,我们要拿到拿到view上的内容如用户的姓名和密码,登录之后页面要跳转,吐司提示等。所以,和view相关的,界面展示相关的,就都写在这里,另外,也不怕写漏掉,接口编程,想往里面添加就添加。

/** * 只和view相关的逻辑 */public interface IUserLoginView {    String getUserName();    String getPassword();    void toDetailActivity(User user);}

3.最后是Module层:连接view和module层,将module中获取的数据设置在view上,完成交互。(我的理解是:presenter调view和module完成交互)。

/** * presenter 主要看要完成什么样的交互 *  */public class UserLoginPresenter {    //1. 登录:    private IUser iUser;    private IUserLoginView userLoginView;    public UserLoginPresenter(IUserLoginView view){        this.userLoginView = view;        this.iUser = new IUserImpl();    }    //登录过程:    public void login(){        iUser.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {            @Override            public void onloginSucced(User user) {                userLoginView.toDetailActivity(user);            }            @Override            public void onloginFailed() {            }        });    }}

4.最后看MainActivity如何做登录处理:

public class MainActivity extends AppCompatActivity implements IUserLoginView {    private EditText et_name;    private EditText et_psw;    private Button btn_login;    //调用Presenter:    private UserLoginPresenter presenter = new UserLoginPresenter(this);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();    }    private void initView() {        et_name = (EditText) findViewById(R.id.et_name);        et_psw = (EditText) findViewById(R.id.et_psw);        btn_login = (Button) findViewById(R.id.btn_login);        btn_login.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //View 要做的事情:交给presenter去做:                presenter.login();            }        });    }    @Override    public String getUserName() {        return et_name.getText().toString();    }    @Override    public String getPassword() {        return et_psw.getText().toString();    }    @Override    public void toDetailActivity(User user) {        Intent intent = new Intent(this,DetailActivity.class);        startActivity(intent);    }}//布局:<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.example.mvptest.view.MainActivity"    android:orientation="vertical"    >    <EditText        android:id="@+id/et_name"        android:layout_width="match_parent"        android:layout_height="40dp" />    <EditText        android:id="@+id/et_psw"        android:layout_width="match_parent"        android:layout_height="40dp"        />    <Button        android:id="@+id/btn_login"        android:layout_width="match_parent"        android:layout_height="50dp" /></LinearLayout>

5.整个调用过程如下: activity中点击登录按钮的时候,调用presenter中的login方法,而presenter中的login又是调用module中的login,module中login方法需要的参数来源又是通过view中的方法得来。

好了,第一个用MVP构建的登录页面完成了,现在我们再接着练习下一个例子:在recycleview页面中如何用MVP来做:

案例二:

view: IDetailView

module:IDetailData , IDetailDataImpl

presenter: DetailDataPresenter

bean: DetailDataBean(只有name,age,addresss三个字段)

1. moudle层:获取数据

//接口类:public interface IDetailData {    ArrayList<DetailDataBean>  getAllDetailData();}//接口的实现类:public class IDetailDataImpl implements IDetailData {    @Override    public ArrayList<DetailDataBean> getAllDetailData() {        ArrayList<DetailDataBean> list = new ArrayList<>();        for(int i = 0;i<20;i++){            DetailDataBean bean = new DetailDataBean("name"+i,i,"address"+i);            list.add(bean);        }        return list;    }}

2. view层:

public interface IDetailView  {   void setAdapter(ArrayList<DetailDataBean> lists);}

3.presenter层:

/** * * view 和 module 层的交互: */public class DetailDataPresenter {    private IDetailData iDetailData;//数据源    private IDetailView iDetailView;//将其绑定到activity    public DetailDataPresenter(DetailActivity view){        this.iDetailData = new IDetailDataImpl();        this.iDetailView = view;    }    public void getData(){       // iDetailData.getAllDetailData();        //view层做业务:        iDetailView.setAdapter(iDetailData.getAllDetailData());    }}

4.Activity:

public class DetailActivity extends AppCompatActivity implements IDetailView {    private RecyclerView mRecyclerView;    private DetailDataPresenter presenter = new DetailDataPresenter(this);    private HomeAdapter mAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_detail);        initView();        presenter.getData();    }    private void initView() {        mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);    }    @Override    public void setAdapter(ArrayList<DetailDataBean> lists) {        mAdapter = new HomeAdapter(lists);        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));        mRecyclerView.setAdapter(mAdapter);    }    public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>{        private ArrayList<DetailDataBean> mData;        public HomeAdapter(ArrayList<DetailDataBean> lists) {            this.mData = lists;        }        @Override        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {            MyViewHolder holder = new MyViewHolder(LayoutInflater.from(DetailActivity.this).inflate(R.layout.item_home, parent,                    false));            return holder;        }        @Override        public void onBindViewHolder(MyViewHolder holder, int position) {            holder.tv1.setText(mData.get(position).getName());            holder.tv2.setText(mData.get(position).getAge()+"");            holder.tv3.setText(mData.get(position).getAddress());        }        @Override        public int getItemCount() {            return mData.size();        }        class MyViewHolder extends RecyclerView.ViewHolder        {            TextView tv1;            TextView tv2;            TextView tv3;            public MyViewHolder(View view)            {                super(view);                tv1 = (TextView) view.findViewById(R.id.tv_name);                tv2 = (TextView) view.findViewById(R.id.tv_age);                tv3 = (TextView) view.findViewById(R.id.tv_address);            }        }    }}//布局很简单:activity中放置一个recycleview. recucleview的item布局是放3个textview,就不贴出来了。

5.调用过程:activity中需要获取数据展示在adapter中,所以先调用presenter中的getData方法,而这个方法又是先调用moudle中的getAllDetailData方法,得到一个数据集合作为参数,返回给view中setAdapter方法。

以上是自己学习mvp的整体过程,google中的todoapp -mvp搭建如下:看个人的习惯吧,只要是符合MVP思想,都可以的。

public interface TaskDetailContract {    interface View extends BaseView<Presenter> {        void showTask(Task task);        void showError();        void showTaskDeleted();        void showTaskMarkedComplete();        void showTaskMarkedActive();        boolean isActive();    }    interface Presenter extends BasePresenter {        void getTask();        void deleteTask();        void completeChanged(Task task, boolean isChecked);    }}
原创粉丝点击