您的位置:首页 > 移动开发 > Android开发

android MVP模式 个人思考

2016-08-17 19:55 525 查看
之前去参加过一个面试,技术面的时候问到我现在开发都用什么架构,我一下懵逼了。这么小的项目还考虑毛框架啊。

这几天又开始新项目框架搭建的时候,时间没那么紧,开始打算考虑android项目的框架问题,看有没有借鉴的地方。对MVP,MVVM进行了大量资料查询,说实话,可能是本人思维有了定式,能看懂MVP的结构,但是对MVP模式依然很难以完全适应。

以下内容全是个人见解,有可能是学习不够,有可能是理解本身不够,未能理解到MVP精髓,欢迎留言指正。

进入正题,关于MVP模式的讲解以及代码结构,网上一搜一大堆,但是我个人感觉,网上除了直接复制粘贴完全一样的,不一样的实现内容之间的代码结构都略有不同。我只拿其中一个实现login的说一说个人理解。

从网上的资料来看,MVP模式作用包括:

1.拆分了Activity文件,大幅度减少Activity中的代码量,方便维护阅读。

2.独立出的view层和model层之间通过presenter进行管理,减少两层之间的耦合,某一层做改动不影响另一层。

3.分层过后方便测试。

4.提高代码复用率。

以上是我个人理解到的MVP模式的好处,但是研究了几个MVP模式的demo后发现,感觉MVP框架的思想有点强行为了分层而分层的感觉,难以一下子适应,而且关键在于MVP中将activity分层到view层,但是activity涉及到的生命周期、广播服务、handler等,在我看来依然属于控制层的范畴,在目前看到demo中,activity不可避免的出现了控制数据流向的代码。

所以基于MVP,我个人调整了下代码结构和逻辑,按照我的理解对项目进行了分层设计。

结构依然分成3层结构,view、controller、model,但是对MVP的实现方式做了调整。

view层不继承activity,通过构造函数或者init方式拿到activity和controller抽象接口,view中仅实现获取界面内容、展示内容的部分。

controller层继承activity,自然也继承了activity的生命周期,以及服务广播等信息来源。controller通过在oncreate中调用view层的init方法,实现界面的初始加载等,其后如果有信息需要展示,通过view实现的方法来进行展示。

model层与MVP的没有区别。都是定义实体类,实现对应的数据存取操作等。

以下是我的代码分层(eclipse下,内存太小,用不上studio):



MainViews:

public class MainViews extends BaseViews<MainControllerInterface> {

private EditText edt_username, edt_password;

private OnClickListener clickListener;

@Override
public void init(final Activity a, final MainControllerInterface c) {
a.setContentView(R.layout.main);

edt_username = (EditText) a.findViewById(R.id.edt_username);
edt_password = (EditText) a.findViewById(R.id.edt_password);

clickListener = new OnClickListener() {

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_login:
User u = new User(getUsername(), getPassword());
if (TextUtils.isEmpty(u.getUsername()) || TextUtils.isEmpty(u.getPassword())) {
return;
}
c.onLoginBtnClicked(u);
break;
default:
break;
}
}
};
a.findViewById(R.id.btn_login).setOnClickListener(clickListener);
}

public boolean onCreateOptionsMenu(Activity a, Menu menu) {
a.getMenuInflater().inflate(R.menu.main, menu);
return true;
}

public boolean onOptionsItemSelected(MainController c, MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_settings:
c.onMenuSettingSelected();
break;
default:
break;
}
return false;
}

protected String getUsername() {
// TODO 验证合法性,弹出提示等
return edt_username.getText().toString();
}

protected String getPassword() {
// TODO 验证合法性,弹出提示等
return edt_password.getText().toString();
}

public void setLoginSucess(Object beanNeedForShow) {
// TODO
}

public void setLoginFailed(Object beanNeedForShow) {
// TODO
}

@Override
public void destory() {
}


MainController:

public class MainController extends Activity implements MainControllerInterface {
private MainViews views;
private UserModel userModel;

// private TestService bleService;处理service
// private ServiceConnection conn;
// private Handler handler;//处理handler内容
// private BroadcastReceiver receiver;//处理广播内容

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (userModel == null) {
userModel = new UserModel(getApplicationContext());
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
return views.onCreateOptionsMenu(this, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
return views.onOptionsItemSelected(this, item);
}

@Override
protected void onResume() {
super.onResume();
}

@Override
protected void onDestroy() {
views.destory();
super.onDestroy();
}

public void onMenuSettingSelected() {
// TODO
}

@Override
public void onLoginBtnClicked(User u) {
// TODO
userModel.login(u, new CallBack() {

@Override
public void onSuccess(User u) {
views.setLoginSucess(new Object());
}

@Override
public void onFailed(User u, Exception e) {
views.setLoginFailed(new Object());
}
});
}

public void setViews(MainViews views) {
this.views = views;
}

}


UserModel:

public class UserModel {

private Context ctx;

public UserModel(Context ctx) {
this.ctx = ctx;
}

public void login(User u, CallBack c) {
// 访问本地数据,网络数据等
// 可以同步传入handler,callback等,以便接收异步数据
// 此处demo直接使用暂定的callback
}

public interface CallBack {
public void onSuccess(User u);

public void onFailed(User u, Exception e);
}
}


demo代码中,我做了login的3层贯通,但是有些具体实现细节没有完全实现。

BaseViews和Controller接口,是我在用这个架构套用在之前的一个小项目上提炼出来的,不是必须。

之前我用过这个分层结构来进行过测试,但是由于我个人以前从未系统的进行android单元测试等,只能简单的用Robolectric进行了一下简单试验。

Model层的测试比较简单。

Controller层是用的笨办法,通过set方法注入了一个空实现的Views和一个直接返回特定结果的Model实现类进行的。

View层因为按照这个分层方式,只会有简单的页面显示功能,个人感觉如果需要,可以直接通过实现一个返回特定结果的Controller来进行点点点测试。

这个是我个人调整后的代码结构,不会更改现有的开发思路,所有的数据都汇集到controller中,再由controller来确定数据流向。分层结构后逻辑简单(有可能因为demo逻辑本来就弱),所有逻辑都在controller中实现,层与层之间也能做到互不影响。

以上是我个人对android的MVP模式的理解和个性化调整,如果有感兴趣的朋友,欢迎拍砖指正交流。

附上我demo的代码:eclipse下的工程,只有全部结构代码,不保证完全运行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android mvp 架构 框架