Mvp想必做Android开发的同学多多少少都会接触一些,今天来分享下基础的MVP架构如何构建
Mvp核心思想:
mvp把activity中ui逻辑抽象成View接口,把业务逻辑抽象成Presenter接口,Model还是原来的Model
优点:
1、activity职责更加明确,完成UI逻辑和使用哪一个表示层
2、代码结构清楚,更容易维护
3、方便单元测试
4、避免Activity的内存泄漏
View层的ui逻辑通过接口关联到表示层,表示层通过Model层的数据接口,实现对数据的操作,关键在于数据回调过程的处理和在构建MVP过程中防止内存泄漏,基础的mvp架构很简单,但是如果想要构建一个通用的架构,还是要费点心思。
由上图可以看出,mvp分层虽然代码相对于mvc复杂一些,但是可以应对频繁的需求变更,无论是View层变化,还是数据源变化,都能够轻松解耦,只关心业务,逻辑不用过多排查,提高了开发效率。
工程代码:
工程结构如下:
下面直接上代码:
package com.example.lixuecheng.mvpshow.view;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.Toast;
import com.example.lixuecheng.mvpshow.R;
import com.example.lixuecheng.mvpshow.adapter.MyAdapter;
import com.example.lixuecheng.mvpshow.bean.Girl;
import com.example.lixuecheng.mvpshow.presenter.GirlPresenter;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends BaseActivity<IGirlView,GirlPresenter<IGirlView>> implements IGirlView{
ListView listView;
GirlPresenter girlPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// List<Girl> datas = new ArrayList<>();
// datas.add(new Girl(R.drawable.first, "小美丽"));
// datas.add(new Girl(R.drawable.second, "小美丽"));
// datas.add(new Girl(R.drawable.third, "小美丽"));
// datas.add(new Girl(R.drawable.fourth, "小美丽"));
// MyAdapter myAdapter = new MyAdapter(this, datas);
listView = findViewById(R.id.mylistview);
// new GirlPresenter<>(this).fetch();
girlPresenter.fetch();
// listView.setAdapter(myAdapter);
// myAdapter.notifyDataSetChanged();
}
@Override
public void showLoading() {
Toast.makeText(this, "加载成功", Toast.LENGTH_SHORT).show();
}
@Override
public void showGirls(List<Girl> girls) {
MyAdapter myAdapter = new MyAdapter(this, girls);
listView.setAdapter(myAdapter);
}
@Override
protected GirlPresenter<IGirlView> creatPresenter() {
return new GirlPresenter<>();
}
}
代码中,BaseActivity将Presenter的初始化封层,通过泛型,将View层的接口传入,从而可以适配更多的VIew,IGirlVIew为View层的接口,根据需求,调整自己的接口,增加或者减少。
直接看后续关键代码;
package com.example.lixuecheng.mvpshow.view;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import com.example.lixuecheng.mvpshow.presenter.BasePresenter;
public abstract class BaseActivity<V, T extends BasePresenter<V>>extends Activity {
public T girlPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
girlPresenter = creatPresenter();
girlPresenter.attchView((V)this);
}
@Override
protected void onDestroy() {
super.onDestroy();
girlPresenter.dettachView();
}
protected abstract T creatPresenter();
}
BaseActivity是抽象类,通过泛型方式,拿到各个View的引用,从而和表示层建立关联。只要继承了BaseActivity,都要实现它的抽象方法,从而拿得到各自View的表示层。
package com.example.lixuecheng.mvpshow.presenter;
import com.example.lixuecheng.mvpshow.bean.Girl;
import com.example.lixuecheng.mvpshow.model.GirlModelImpl;
import com.example.lixuecheng.mvpshow.model.IGirlModel;
import com.example.lixuecheng.mvpshow.view.IGirlView;
import java.lang.ref.WeakReference;
import java.util.List;
/**
* 表示层
*/
public class GirlPresenter<T extends IGirlView> extends BasePresenter<T>{
//view层引用
// IGirlView girlView;
//model层引用
IGirlModel iGirlModel = new GirlModelImpl();
//model层引用
//构造方法
public GirlPresenter() {
// this.girlView = view;
// mViewRef = new WeakReference<>(view);
}
//执行数据
public void fetch() {
if(mViewRef != null) {
mViewRef.get().showLoading();
if(iGirlModel != null) {
iGirlModel.loadGirl(new IGirlModel.GirlOnLoadListener() {
@Override
public void onComplete(List<Girl> girls) {
if(mViewRef != null) {
mViewRef.get().showGirls(girls);
}
}
});
}
}
}
}
注意这里的GirlPresenter的实例化中,什么都没有做,而是将绑定View的工作都放到父类当中。
package com.example.lixuecheng.mvpshow.presenter;
import java.lang.ref.WeakReference;
public class BasePresenter<T> {
protected WeakReference<T> mViewRef;
//进行绑定
public void attchView(T view) {
mViewRef = new WeakReference<>(view);
}
//进行解绑
public void dettachView() {
mViewRef.clear();
}
}
通过弱引用的方式,定义view的引用,同时将绑定和解绑都通过弱引用方式完成,防止内存泄漏。这里面还有个小技巧就是数据的回调,没有采用直接数据填充回调,因为如果是网络数据,没有数据返回时候,会一直等待,具体见项目。
项目github地址:https://github.com/lixuecheng/Multi_Mvp.git