本文旨在从零到一搭建一个mvp框架、对于mvp不了解的看这篇文章
正文开始
在里面新建两个接口(Interface),分别取名 BaseView 和 BaseModel,这里定义一些公共方法
public interface BaseView {
void showLoading();
void hideLoading();
void showError();
}
public interface BaseModel {
}
接下来定义一个抽象类,取名 BasePresenter
public abstract class BasePresenter {
protected M mModel;
//弱引用的写法,避免内存泄漏。
protected WeakReference mView;
protected void onAttach(M m, V v) {
mView = new WeakReference<>(v);
mModel = m;
}
//检测 V 是否已关联 P
protected boolean isViewAttached() {
return null != mView && null != mView.get();
}
protected V getView() {
return isViewAttached() ? mView.get() : null;
}
protected void onDetach() {
if (null != mView) {
mView.clear();
mView = null;
}
}
}
该类则用于反射获取指定泛型
public class ReflectUtil {
public static T getT(Object o, int i) {
try {
return ((Class) ((ParameterizedType) (o.getClass().getGenericSuperclass())).getActualTypeArguments()[i]).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
接下来定义BaseActivity,举一反三BaseFragment同理
public abstract class BaseActivity extends AppCompatActivity implements BaseView {
protected T mPresenter;
protected M mModel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
//通过反射获取presenter model对象
mPresenter = ReflectUtil.getT(this, 0);
mModel = ReflectUtil.getT(this, 1);
//绑定
mPresenter.onAttach(mModel, this);
initView();
}
protected abstract int getLayoutId();
protected abstract int initView();
@Override
public void showLoading() {
}
@Override
public void hideLoading() {
}
@Override
public void showError() {
}
@Override
protected void onDestroy() {
super.onDestroy();
//解绑
mPresenter.onDetach();
}
}
创建接口 MvpListener,用于数据从 M 到 V 的层间传递
public interface MvpListener {
void onSuccess(T result);
void onError(String errorMsg);
}
接下来创建一个Contract,来归纳创建view、model、presenter接口,这里可以使用插件mvphelper,省去创建类的步骤
public interface MainContract {
interface Model extends BaseModel {
void loadDaily(String url, MvpListener listener);
}
interface View extends BaseView {
void setData(String s);
}
abstract class Presenter extends BasePresenter {
abstract void loadData(String url);
}
}
然后实现这三层,首先是presenter
public class MainPresenter extends MainContract.Presenter {
@Override
protected void loadData(String url) {
MainContract.View mView = getView();
if (mView == null) {
return;
}
mView.showLoading();
//调用model方法,获取网络请求回调结果
mModel.loadDaily(url, new MvpListener() {
@Override
public void onSuccess(String result) {
mView.hideLoading();
mView.setData(result);
}
@Override
public void onError(String errorMsg) {
mView.hideLoading();
mView.showError();
}
});
}
}
接下来是model,我这里网络请求使用的okgo,这个根据自己喜好用什么都一样,需要在成功跟失败的回调里去调用自定义的mvplistener
public class MainModel implements MainContract.Model {
@Override
public void loadDaily(String url, MvpListener listener) {
//这里执行网络请求操作
OkGo.get(url).execute(new StringCallback() {
@Override
public void onSuccess(Response response) {
listener.onSuccess(response.body());
}
@Override
public void onError(Response response) {
super.onError(response);
listener.onError(response.body());
}
});
}
}
最后是view,也就是我们的activity
public class MainActivity extends BaseActivity implements MainContract.View {
private static final Locale LOCALE = Locale.CHINA;
@Override
protected int getLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initView() {
mPresenter.loadData("http://news.at.zhihu.com/api/4/news/before/" + format(new Date(), "yyyyMMdd"));
}
@Override
public void setData(String s) {
Toast.makeText(this, "请求结果" + s, Toast.LENGTH_SHORT).show();
}
public static String format(Date date, String s) {
return new SimpleDateFormat(s, LOCALE).format(date);
}
}
本文意在搭建mvp,就不去做数据列表展示了,在这里做了一个toast,贴上成功的截图
最后,到这里mvp框架就搭建完毕了,总结一下实现过程
这里贴上我的demo,需要的可以下载参考一下 https://download.csdn.net/download/zyz18813049204/16303268