MVP的实践

背景:

之前看到有朋友在项目中用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);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值