精辟句:什么叫燃烧自己,温暖别人,就是火葬场里烧锅炉。
在移动没有出现之前,大家一直使用的MVC,MVC是80年代的架构模式,但是但是出现一直没有火起来,后台出现了SSM,SSH等后台框架,MVC才得到很好地发挥。
MVC全称是Model - View - Controller,是模型(model)-视图(view)-控制器(controller)的缩写。MVC是一种框架模式而非设计模式,GOF把MVC看作是3种设计模式:观察者模式、策略模式与组合模式的合体,而核心是观察者模式。简而言之,框架是大智慧,用来对软件设计进行分工;设计模式是小技巧,对具体问题提出解决方案,以提高代码复用率,降低耦合度。
MVC在后台中使用的相当好,但是当在移动端使用MVC却不是那么回事,在移动端通常会把Activity/Fragment视作Controller,在项目较小的时候,Activity/Fragment所写代码并不是很多,所以在感觉上还好,但是一旦代码量上来的时候,就会感觉Activity/Fragment所写代码太多,显得十分臃肿。在Activity/Fragment中既有VC交互,而且还有MC交互和MV交互,这样使项目维护起来难度大了很多。
基于以上等等原因,于是MVP架构在最近两年出现了。所说MVP是MVC演化版本,但是两者之间还是有很大的区别,主要区别是在MVP中去除了MV交互,Activity/Fragment属于View层。
MVP模式会解除View与Model的耦合,有效的降低View的复杂性。同时又带来了良好的可扩展性、可测试性,保证系统的整洁性和灵活性。
MVP模式可以分离显示层与逻辑层,它们之间通过接口进行通信,降低耦合。理想化的MVP模式可以实现同一份逻辑代码搭配不同的显示界面,因为它们之间并不依赖与具体,而是依赖于抽象。这使得Presenter可以运用于任何实现了View逻辑接口的UI,使之具有更广泛的适用性,保证了灵活度。
MVP模式的三个角色
Presenter – 交互中间人:Presenter主要作为沟通View与Model的桥梁,它从Model层检索数据后,返回给View层,使得View与Model之间没有耦合,也将业务逻辑从View角色上抽离出来。
View – 用户界面:View通常是指Activity、Fragment或者某个View控件,它含有一个Presenter成员变量。通常View需要实现一个逻辑接口,将View上的操作转交给Presenter进行实现,最后,Presenter 调用View逻辑接口将结果返回给View元素。
Model – 数据的存取:Model 角色主要是提供数据的存取功能。Presenter 需要通过Model层存储、获取数据,Model就像一个数据仓库。更直白的说,Model是封装了数据库DAO或者网络获取数据的角色,或者两种数据方式获取的集合。
在实现之前,首先看看Google MVP Demo。
项目结构分析
假设在MainActivity中要显示一个ListView列表数据。如果采用MVP架构,就必须有View,Presenter和Model三层。
一、View:创建IMainView接口,定义对所有视图控件操作方法,在MainActivity实现该接口。
二、Model:创建PersonModel接口,定义对数据处理的操作方法,在PersonModelImpl类中实现。
三、Presenter:创建MainPresenter类,实现视图控件和数据绑定。
MVC项目结构图:
Model层:
1、Person - Java Bean文件,保存人物相关信息:
/**
* 人物类
* Created by 邹峰立 on 2018/3/16.
*/
public class Person {
private String name;
private String address;
public Person() {
super();
}
public Person(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
2、PersonModel - 定义数据操作方法:
/**
* 人物 model 接口
* <p>
* Created by 邹峰立 on 2018/3/16.
*/
public interface PersonModel {
/**
* 获取人物消息列表
*/
void getPersonList(PersonModelListener personModelListener);
// 定义回调接口 - 避免网络数据延迟
interface PersonModelListener {
void onComplete(ArrayList<Person> list);
}
}
3、PersonModelImpl - PersonModel接口实现类:
/**
* 人物接口实现类
* Created by 邹峰立 on 2018/3/16.
*/
public class PersonModelImpl implements PersonModel {
// 从本地/网络访问获取数据
@Override
public void getPersonList(PersonModelListener personModelListener) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("张三", "张三张三张三张三张三张三张三张三张三张三张三"));
list.add(new Person("李四", "李四李四李四李四李四李四李四李四李四李四李四"));
list.add(new Person("王五", "王五王五王五王五王五王五王五王五王五王五王五"));
list.add(new Person("赵六", "赵六赵六赵六赵六赵六赵六赵六赵六赵六赵六赵六"));
list.add(new Person("钱七", "钱七钱七钱七钱七钱七钱七钱七钱七钱七钱七钱七"));
list.add(new Person("孙八", "孙八孙八孙八孙八孙八孙八孙八孙八孙八孙八孙八"));
list.add(new Person("周九", "周九周九周九周九周九周九周九周九周九周九周九"));
list.add(new Person("吴十", "吴十吴十吴十吴十吴十吴十吴十吴十吴十吴十吴十"));
if (personModelListener != null)
personModelListener.onComplete(list);
}
}
Presenter层:
1、BasePresenter - Presenter基类:
/**
* Presenter基类
* <p>
* T 视图实现接口
* <p>
* Created by 邹峰立 on 2018/3/16.
*/
public class BasePresenter<V> {
WeakReference<V> mViewRef;// 虚引用
// 绑定mViewRef
public void attachView(V view) {
mViewRef = new WeakReference<>(view);
}
// mViewRef解绑
public void detachView() {
mViewRef.clear();
}
}
2、MainPresenter - 实现Model和View的交互:
/**
* 人物 Presenter
* Created by 邹峰立 on 2018/3/16.
*/
public class MainPresenter<T extends IMainView> extends BasePresenter<T> {
// model层
private PersonModel personModel = new PersonModelImpl();
// 绑定数据
public void bindData() {
if (mViewRef.get() != null) {
mViewRef.get().showLoadToast();
if (personModel != null) {
personModel.getPersonList(new PersonModel.PersonModelListener() {
@Override
public void onComplete(ArrayList<Person> list) {
mViewRef.get().showData(list);
}
});
}
}
}
}
View层:
1、IMainView - 定义MainActivity中相关控件操作方法:
/**
* 人物 界面 接口
* Created by 邹峰立 on 2018/3/16.
*/
public interface IMainView {
// 展示加载数据Toast
void showLoadToast();
// 展示数据(使用回调的方式还回数据)
void showData(ArrayList<Person> list);
}
2、BaseActivity - Activity基类:
/**
* Activity 基类
* Created by 邹峰立 on 2018/3/16.
*/
public abstract class BaseActivity<V, T extends BasePresenter<V>> extends AppCompatActivity {
T basePresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
basePresenter = initPresenter();
basePresenter.attachView((V) this);
}
@Override
protected void onDestroy() {
super.onDestroy();
basePresenter.detachView();
}
// 初始化Presenter
protected abstract T initPresenter();
}
3、MainActivity - IMainView接口的实现类,视图显示类:
/**
* MVP构架实践
*/
public class MainActivity extends BaseActivity<IMainView, MainPresenter<IMainView>> implements IMainView {
private ListView listView;
private MainLvAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listview);
basePresenter.bindData();
}
@Override
protected MainPresenter<IMainView> initPresenter() {
return new MainPresenter<>();
}
@Override
public void showLoadToast() {
Toast.makeText(this, "加载数据...", Toast.LENGTH_LONG).show();
}
@Override
public void showData(ArrayList<Person> list) {
setAdapter(list);
}
// 自定义setAdapter
public void setAdapter(ArrayList<Person> list) {
if (adapter == null) {
adapter = new MainLvAdapter(MainActivity.this, list);
listView.setAdapter(adapter);
} else {
adapter.reflashData(list);
}
}
}
4、MainLvAdapter - ListView的适配器:
/**
* 人物Adapter
*
* Created by 邹峰立 on 2018/3/16.
*/
public class MainLvAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private ArrayList<Person> mDatas;
public MainLvAdapter(Context context, ArrayList<Person> list) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.mDatas = list;
}
public void reflashData(ArrayList<Person> list) {
this.mDatas = list;
this.notifyDataSetChanged();
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public Object getItem(int position) {
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.activity_main_lv_item, parent, false);
holder.nameTv = convertView.findViewById(R.id.tv_name);
holder.addressTv = convertView.findViewById(R.id.tv_address);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Person person = mDatas.get(position);
holder.nameTv.setText(person.getName());
holder.addressTv.setText(person.getAddress());
return convertView;
}
static class ViewHolder {
TextView nameTv, addressTv;
}
}
最终效果图:
MVP结构不一定是最好的结构,相对于MVC而言,可能在结构上清晰一些,但也要针对不同的项目以及你目前处于什么样的一个项目组,所以并不能说MVC比MVP差,或者说MVP比MVC好。
微信公众号:伴职创作