上一篇文章介绍了我常用的一些框架,也是为我现在要讲的一个MVP小Demo做了个铺垫,没看过的客官可以瞅瞅这些常用的框架 -- Android项目框架从搭建到放弃(一)
在我写Android学习MVP架构的最简单方法的时候,我也是刚开始学习这个模式,看了不少用MVP模式写的demo,感觉各有千秋但仍不如我意。因为他们没有进行很好的优化,虽然看似减轻了Activity的负担,但是增加很多类文件,使用起来仍很费劲。
因此我自己琢磨出来一个写法,只为给大家提供一个思路。
先贴一张项目结构图:
- Model层分为Json转换的Bean对象和View的接口,即BaseView,所有的View都共用这一个BaseView,BaseListView继承BaseView增加获取Adapter等其他方法。
- View层就是各个Activity,Fragment,Pager页面。
- Presenter层只有一个BasePresenter,所有的Activity和Fragment都用它来做网络请求等耗时操作,BaseListPresenter继承BasePresenter来处理有刷新和加载的列表页面,如果有其他情况可以自己写个子类继承BasePresenter来复写父类的默认加载方法或者增加其他方法(例如BaseListPresenter)。
BaseView
public interface BaseView {
/**
* 显示loading
*/
void showLoading();
/**
* 隐藏loading
*/
void hideLoading();
/**
* 获取更新ui的接口url
* @return
*/
String getDefaultUrl();
/**
* 更新ui数据
*/
void setViewData(String data);
/**
* 没有网络
*/
void noNetWork();
/**
* 服务器异常,不是200时候的处理
*/
void isNotTwohundred(BaseResponse response);
}
BaseActivity :
public abstract class BaseActivity extends AppCompatActivity implements BaseView, NetEventHandler {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
synchronized (mActivities) {
mActivities.add(this);
}
onBeforeSetContentLayout();
setContentView(getLayoutId());
presenter = getPresenter();
initActionBar();
init(savedInstanceState);
initView();
if (isLoadDefault()) { //如果默认需要加载数据,就去请求网络
presenter.loadDefaultData(); //请求网络操作在presenter中,结果会回调给activity
}
}
//省略...
}
BasePresenter
public class BasePresenter {
public Context context;
public BaseView view;
public BaseListView listView;
public BasePresenter(Context context, BaseListView baseListView) {
this.context = context;
this.listView = baseListView;
}
public BasePresenter(Context context, BaseView view) {
this.context = context;
this.view = view;
}
/**
* 默认加载页面数据
*/
public void loadDefaultData(){
String url = view.getDefaultUrl();
if(!checkUrl(url)) return;
view.showLoading();
OkHttpUtils.get().url(url).headers(RequestHeaders.headers()).tag(url).build().execute(new StringCallBack(context) {
@Override
public void onResponse(BaseResponse response, int id) {
if(response!=null&&response.isOk()){
view.setViewData(response.getData());
}else if(response!=null){
view.isNotTwohundred(response);
}
}
@Override
public void onError(Call call, Exception e, int id) {
super.onError(call, e, id);
view.noNetWork();
}
@Override
public void onAfter(int id) {
super.onAfter(id);
if(view!=null){
view.hideLoading();
}
}
});
}
//省略部分请求方法...
private boolean checkUrl(String url){
if(TextUtils.isEmpty(url)){
LogUtils.d("url为空,不加载数据");
return false;
}else if(!url.startsWith("http")){
LogUtils.d("url类型错误");
return false;
}
if(TDevice.getNetworkType()==0){
LogUtils.e("网络连接异常");
view.noNetWork();
return false;
}
return true;
}
}
这里贴出部分代码,大体的思路就是我不再像之前那样,为每一个View都去创建一个presenter和model,使用公用的,如果有特殊要求继承一个就行了。
举个Activity页面的小栗子:
public class DemoActivity extends BaseActivity {
private TextView mTvName;
@Override
protected int getLayoutId() {
return R.layout.activity_demo;
}
/**
* 如果本页面不需要加载数据返回null即可
* @return
*/
@Override
public String getDefaultUrl() { return HttpManager.DEMO_URL; }
@Override
protected void initView() {
mTvTitle.setText("Demo");
mTvName = getView(R.id.mTvName);
//执行一个get请求,presenter.getRequest()
mTvName .setOnClickListener(v->getRequest());
//执行一个post请求,presenter.postRequest()
mTvName .setOnClickListener(v->postRequest());
}
@Override
public void setViewData(String data) {
DemoBean demoBean = GsonTools.changeGsonToBean(data, DemoBean.class);
mTvName.setText(demoBean.getName());
}
private void getRequest() {
presenter.getRequest(HttpManager.DEMO_URL, new StringCallBack(this) {
@Override
public void onResponse(BaseResponse response, int id) {
mTvName.setText(response.getData());
}
});
}
private void postRequest() {
if(mTvName.getText().toString().length()<10){
UIUtils.showToast("用户名太短,请重新输入");
return;
}
presenter.postRequest(HttpManager.DEMO_URL, getRequestBody(), new StringCallBack(this) {
@Override
public void onResponse(BaseResponse response, int id) {
mTvName.setText(response.getData());
}
});
}
}
这就是我自己琢磨的一种MVP写法,大家可以参考一下,其实写的也不是很完善,还有很多可以优化的地方,代码已经上传至GitHub,有什么建议欢迎留言评论。
GitHub地址 ZzMvp 大爷随手start一下(*  ̄3)(ε ̄ *)
用JitPack把我的基类和常用的工具类整成了一个library,只是为了日后自己使用方便,会一直来优化的,只需关联一下,一行代码搭建起来一个项目框架!(扩展性会逐渐增强)
使用方法:
//Add it in your root build.gradle at the end of repositories:
allprojects {
repositories { ...
maven { url "https://jitpack.io"
}
}
}
//Add the dependency [Latest release](https://github.com/itzhong/ZzMvp/releases/latest)
dependencies {
compile 'com.github.itzhong:ZzMvp:V1.0.2'
}
下面就是我用这个library来写的一个DemoGIF:
谢谢观看。