Android_从创建项目开始学习MVP由入门到放弃

之前的项目一直使用mvc的模式编写,动不动一个Activity的代码就达到了成百上千行,每次改需求和BUG都需要上下滑从几百行代码里找到关键位置十分的难受+浪费时间.于是学习了一下MVP模式,解耦一下代码,方便后期的维护.

一.回顾MVC

    在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。

1.M(Model)模型层

    对数据库的操作,访问网络等都应该放在Model中

2.V(View)视图层

    即xml文件对界面的描述

3.C(control)控制层

    Android的控制层通常交给了Actvity,所以尽量不要再Acticity中写代码,应该将一些业务逻辑交给Model层处理

二.学习MVP

    在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部.而在MVC中View会直接从Model中读取数据而不是通过 Controller


  1.M(Model)模型层
    对数据库的操作,访问网络等都应该放在Model中

  2.V(View)视图层

    即xml文件对界面的描述

  3.P(Presenter)

    负责在Model和View之间,从model里取出数据,格式化后在View上展示(解决如何把数据和用户界面放在一起)。

而和MVC最大的区别在于Model和View完全被Presenter隔开了,Presenter作为它们之间的中间人去传递所有数据。

三:从新建项目开始学习MVC

3.1 新建项目并分包


3.2 创建BaseActivity并被MainActivity继承

BaseActivity放在根目录,MainActivity放在view -> ui 包中

public abstract class BaseActivity extends Activity {

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

        initUI();

        initData();

        initLinsenter();
    }
    
    public abstract void initUI();

    public abstract void initData();

    public abstract void initLinsenter();
}
public class MainActivity extends BaseActivity {

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

    }

    //继承至baseActivity的方法
    @Override
    public void initUI() {
        setContentView(R.layout.activity_main);
    }

   //继承至baseActivity的方法
    @Override
    public void initData() {

    }

    //继承至baseActivity的方法
    @Override
    public void initLinsenter() {

    }
}

3.3 创建请求json解析数据数据的bean类

  bean类放在model -> bean 包中

public class BookBean {

    public String name;
    public int price;
    
    public BookBean(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

 
}
3.4 创建IBookView

    放在view包下

 这里主要是包含了Activity的一系列关于UI操作,然后用我们的Activity去实现,这样Presenter就可以调用了。

    

public interface IBookView {

    /**
     * 刷新数据
     */
     void refreshAdapter();

    /**
     * 提示吐司
     * @param msg
     */
     void Toast(String msg);

    /**
     * 请求数据为空
     */
    void OnEmpty();
}
3.5 创建创建全局通用的请求数据回调ValueCallBack
    放在根目录下

public interface ValueCallBack<T> {

   //请求成功回调
   void Onsuccess(T t);

   //请求失败的回调
   void OnError(String msg);

}

3.6 创建IBuyBookModel
放在model包底层
public interface IBuyBookModel {

    /**
     * 请求网络取数据
     * @param callback
     */
    void getTestData(ValueCallback<List<BookBean>> callback);


    /**
     * 返回本地adapter的数据
     * @return
     */
    List<BookBean> getAdapterData();
}
3.7 创建BuyBookModel实现IBuyBookModel,进行网络请求

放在model -> task 包中

public class BuyBookModel implements IBuyBookModel {

    private final ArrayList<BookBean> bookBeans;

    public BuyBookModel() {

        bookBeans = new ArrayList<>();
    }

    //重写至IBuyBookModel
    @Override
    public void getTestData(final ValueCallBack<List<BookBean>> callback) {
        //模拟网络请求
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {

                ArrayList<BookBean> bookBeans = new ArrayList<>();
                bookBeans.add(new BookBean("android",99));
                bookBeans.add(new BookBean("ios",188));
                bookBeans.add(new BookBean("java",666));
                bookBeans.add(new BookBean("php",123));
                //随机数模拟返回的code
                Random random = new Random();
                int code = random.nextInt(5);
                if(code==3){
                    callback.Onsuccess(bookBeans);
                }else{
                    callback.OnError("暂无数据");
                }
            }
        }, 1000);

    }


    //重写至IBuyBookModel
    @Override
    public List<BookBean> getAdapterData() {

        return bookBeans;
    }
}
3.8 创建BasePresenter

放在根目录下

/**
 * 这个是所有Presenter的基类,里面有个initData()方法,基本每个Presenter都要处理网络请求,所以有了这么一个基类
 为什么用了个泛型?为了让人一看这个Presenter就知道这对应着哪个Activity,实际上这可以不加的,但是我觉得加上去更好。便于后来人也便于自己以后再来修改这个类。
 * @param <T>
 */
public abstract class BasePresenter<T extends BaseActivity> {

    abstract void initData();
}
3.9 创建IBuyBookPresenter以供BuyBookPresenter实现

放在presenter包下

public interface IBuyBookPresenter {

    List<BookBean> getAdapterData();
}

/**
 * 在此处联系model和view
 */
public class BuyBookPresenter extends BasePresenter<MainActivity> implements IBuyBookPresenter {

  public IBuyBookModel bookModel;
  public IBookView iBookView;


    public BuyBookPresenter(IBookView iBookView) {
        this.iBookView = iBookView;
        this.bookModel = new BuyBookModel();
    }

    //重写IBuyBookPresenter的方法
    @Override
    public List<BookBean> getAdapterData() {

        return bookModel.getAdapterData();
    }

    //重写BasePresenter的方法
    @Override
    public void initData() {

        //弹出dialog
        bookModel.getTestData(new ValueCallBack<List<BookBean>>() {
            @Override
            public void Onsuccess(List<BookBean> bookBeans) {
                //关闭dialog
                bookModel.getAdapterData().addAll(bookBeans);
                iBookView.refreshAdapter();
            }

            @Override
            public void OnError(String msg) {
                //关闭dialog
                iBookView.OnEmpty();
                iBookView.Toast(msg);
            }
        });


    }
}
4.1 BaseActivity加入presenter
public abstract class BaseActivity <T extends BasePresenter>  extends Activity {

    protected T basepresenter;

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

        basepresenter = initPresent();

        initUI();

        initData();

        initLinsenter();


    }

    public abstract T initPresent();

    public abstract void initUI();

    public abstract void initData();

    public abstract void initLinsenter();
}

4.2 最终Activity extends BaseActivity<BuyBookPresenter> implements IBuyBookView

放在 view -> ui 包下

public class MainActivity extends BaseActivity<BuyBookPresenter>implements IBookView {

    private RecyclerView recyclerView;
    private BaseAdapter baseAdapter;

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

    }

    @Override
    public BuyBookPresenter initPresent() {
        return new BuyBookPresenter(this);
    }

    //继承至baseActivity的方法
    @Override
    public void initUI() {
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.rv);
    }

   //继承至baseActivity的方法
    @Override
    public void initData() {
        baseAdapter = new BaseAdapter(basepresenter.getAdapterData(), this);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
        recyclerView.setAdapter(baseAdapter);
        basepresenter.initData();
    }

    //继承至baseActivity的方法
    @Override
    public void initLinsenter() {

    }

    //实现至IBookView的方法
    @Override
    public void refreshAdapter() {
        baseAdapter.notifyDataSetChanged();
    }

    //实现至IBookView的方法
    @Override
    public void Toast(String msg) {
        Toast.makeText(getApplicationContext(),msg,Toast.LENGTH_SHORT).show();
    }
    //实现至IBookView的方法
    @Override
    public void OnEmpty() {
        //展示暂无数据的逻辑,如显示为空的图片,隐藏列表
    }
}
附件:
BaseAdapter.java:

放在view -> adapter 包下

package com.demo.zengke.mvpdemo.view.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.demo.zengke.mvpdemo.R;
import com.demo.zengke.mvpdemo.model.bean.BookBean;

import java.util.List;

/**
 * Created by Administrator on 2018/5/24 0024.
 */

public class BaseAdapter extends RecyclerView.Adapter<BaseAdapter.BaseHolder> {

    public List<BookBean> mList;
    public  Context mcontext;


    public BaseAdapter(List<BookBean> lists, Context context) {
        this.mList = lists;
        this.mcontext = context;
    }

    @Override
    public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        BaseHolder holder = new BaseHolder(LayoutInflater.from(mcontext).inflate(R.layout.item_anjianrenyuan_dailiren, parent,
                false));
        return holder;
    }

    @Override
    public void onBindViewHolder(BaseHolder holder, int position) {
        holder.textView.setText(mList.get(position).getName()+mList.get(position).getPrice());
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    public class BaseHolder extends RecyclerView.ViewHolder {

        TextView textView;

        public BaseHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.tv);
        }
    }
}
R.layout.item_anjianrenyuan_dailiren.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:text="========="
        android:textSize="15dp" />

</RelativeLayout>

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.demo.zengke.mvpdemo.view.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.constraint.ConstraintLayout>

最后:

附上,目录结构图:


运行效果图:


感谢大佬点击打开链接

以后有空再上传demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值