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

浅学使用Android的mvp模式+otto消息总线

2016-02-23 15:09 721 查看
对于mvp模式,越来越受到android开发者的关注,前段时间通过朋友知道的他们公司产品使用了mvp+otto模式重构项目,反馈效果不错,借此也自己去结合下,感觉有利有弊,具体的选择,可能要根据产品的应用场景和技术人员的模式定向吧!

先看下效果图吧:



项目结构目录



otto:图中的BusManage

通过定一个获取bus对象,建立单例模式,节约内存消耗,也方便之后调用。

public class BusManager extends Bus {

private static class InterInstance{
private static final BusManager instance = new BusManager();
}

private BusManager(){
}

public static BusManager getInstance(){
return InterInstance.instance;
}
}


以上通过创建静态内部类来实现单例,具体好处是,这种方式并未加锁,因为第一次加载BusManager类时,并不会实例化单例对象,只有第一次调用getInstance()方法时会导致虚拟机加载InterInstance类,这种

方式不仅能保证对象的单一性,还避免加锁带来的性能问题,又启动了延迟加载的优化。

MainBean:实体类

public class MainBean {

private String name;
private String phone;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

}


MainBean用于封装数据的实体类

View:图中IMainView和MainActivity

View相对应于Activity,我们通过创建一个View的接口跟presenter进行交互,降低耦合,View通过实现这个接口去绘制视图,与用户交互。

public interface IMainView {

void showLoading();

void hideLoading();

void showError();

void showResult(MainBean bean);
}


视图接口提供四个接口方法:显示加载视图、隐藏加载视图、显示加载失败视图、显示成功数据

public class MainActivity extends AppCompatActivity implements IMainView {

private RelativeLayout rlLoading;
private RelativeLayout rlError;
private android.widget.TextView tvResult;
MainPresenter mainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.tvResult = (TextView) findViewById(R.id.tvResult);
this.rlError = (RelativeLayout) findViewById(R.id.rlError);
this.rlLoading = (RelativeLayout) findViewById(R.id.rlLoading);
mainPresenter = new MainPresenter(this);
mainPresenter.loadData();
rlError.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mainPresenter.clickError();
}
});
}

@Override
public void showLoading() {
rlLoading.setVisibility(View.VISIBLE);
rlError.setVisibility(View.INVISIBLE);
}

@Override
public void hideLoading() {
rlLoading.setVisibility(View.INVISIBLE);
}

@Override
public void showError() {
hideLoading();
rlError.setVisibility(View.VISIBLE);
}

@Override
public void showResult(MainBean bean) {
tvResult.setText(bean.getName()+bean.getPhone());
}

@Override
protected void onDestroy() {
super.onDestroy();
mainPresenter.unRegister();
}
}


通过实现View接口,去完成用户交互需求。通过创建Presenter对象去处理view和model之间关系。

Model:图中IMainModel和MainModel

我们也需要创建一个抽象接口(IMainModel)来降低耦合,也利于单元测试,model通过实现接口来处理数据。

public interface IMainModel {

void loadMainData();

void clickError();
}


model的接口。提供加载数据和重新点击加载失败页面处理方法

public class MainModel implements IMainModel {

@Override
@Produce
public synchronized void loadMainData() {//模拟加载数据

new AsyncTask<String,String,String>(){

@Override
protected String doInBackground(String... params) {
try {
Thread.sleep(3000);

} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
MainBean bean = new MainBean();
bean.setName("WX_JIN");
bean.setPhone("交流群:313870489");
if ((Math.random()*2) >1.5){//模拟加载数据成功或者失败
BusManager.getInstance().post("获取数据失败");
}else{
BusManager.getInstance().post(bean);
}
}
}.execute();

}

@Override
public void clickError() {
loadMainData();
}
}


model实现类,处理加载数据。这边就是通过otto消息总线去分发加载数据后处理结果。

Presenter:图中MainPresenter

中间枢纽Presenter,作为model和view之间的交互。

public class MainPresenter {

private IMainView mainView;
private IMainModel mainModel;

public MainPresenter(IMainView mainView){
this.mainView = mainView;
this.mainModel = new MainModel();
BusManager.getInstance().register(this);
}

//加载数据
public void loadData(){
mainView.showLoading();
mainModel.loadMainData();
}

public void clickError(){
mainView.showLoading();
mainModel.clickError();
}

public void unRegister(){
BusManager.getInstance().unregister(this);
}

@Subscribe //成功返回数据
public void getSuccessData(MainBean bean){
mainView.hideLoading();
mainView.showResult(bean);
}

@Subscribe //失败返回
public void getError(String error){
mainView.showError();
}
}


Presenter通过去实例化model接口和获取实例化的view接口去处理两者之前的数据。Presenter这边使用otto获取到Model处理完数据之后,再通过View的抽象接口更新View显示的信息。这样就实现了完整的解耦UI与逻辑操作。

如果UI有涉及ListView的Adapter,这样就要在View和Presenter中多出一个Adapter,通过这个Adapter来操作Model和View,Adapter需要实现View接口,这要就保证与Presenter之间的关联不变,扩展性也比较强,也有更好的灵活性。

以上就是自己尝试用mvp和otto一起使用,总结和记录下自己过程中的经验,其中肯定有许多不足,希望日后慢慢补充和修复。

项目源码下载路径

私家博客:http://soubw.com/

CSDN:http://blog.csdn.net/wx_jin
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: