[Android学习]Android中MVP模式初探1

前言:

  1. 初识MVP模式时,看到它缺点是需要增加一倍的类的维护量。所以就暂时没用它。但是,当一个类的代码行数达到一定的量(1000行以上),这时候维护类变得好麻烦,主要是功能变得多了,方法数量也变多了。这个时候真的是需要给类“瘦瘦身”。
  2. 这时候重新看了MVP模式,确实发现了“宝”。

一、简单定义

Model层:将功能逻辑等封装才model层中,其中包括了Data的交互(数据库、网络等),一般用作为接口实现来给Presenter层调用。
View层:一般是Activity或fragment,主要是封装好用于交互界面用的方法,也是一般用作为接口实现来给Presenter层调用和调用Presenter反馈界面交互。
Presenter层:我认识它是作为MVP模式中关键的一层,用户交互的操作通过View层传到这里,Presenter调用Model层和View层的方法来完成功能的流程(我们可以理解View层和Model层的方法大部分都不会在自己内部被调用,而是通过实例被Presenter层调用),然后通过View层反馈给用户。

二、使用一个简单的例子来实现一下

这里我们写个简单计算器的Demo来实现下。

Model层

先定义接口,这里我们写的方法都是功能逻辑的处理。

1
2
3
4
5
6
7
8
9
10
public interface CalcModel
{

/**
* 这里做一个简单的计算
* @param num1
* @param num2
* @return
*/

int doSimpleCalc(int num1, int num2);
}

写实现类,与该层中没有持有其他层的引用。

1
2
3
4
5
6
7
8
public class CalcModelImpl implements CalcModel
{

@Override
public int doSimpleCalc(int num1, int num2)
{

return num1+num2;
}
}

View层

同样,先写接口,这里我写的方法都是和界面交互相关的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public interface CalcView
{

/**
* 初始化
*/

void init();

/**
* 获取数1的值
* @return
*/

int getNum1();

/**
* 获取数2的值
* @return
*/

int getNum2();

/**
* 显示结果值
* @param result
*/

void setCalcResult(int result);
}

再写实现类(Activity),持有Presenter的引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class MainActivity extends Activity implements CalcView,View.OnClickListener
{

private EditText mEtNum1;
private EditText mEtNum2;
private TextView mTvResult;
private Button mBtnCalc;

private CalcPresenter mPresenter;

@Override
protected void onCreate(Bundle savedInstanceState)
{

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 实例化Presenter层
mPresenter=new CalcPresenterImpl(this);
// 初始化
mPresenter.onCreate();
}

@Override
public void init()
{

mEtNum1= (EditText) findViewById(R.id.et_num1);
mEtNum2= (EditText) findViewById(R.id.et_num2);
mTvResult= (TextView) findViewById(R.id.tv_result);

mBtnCalc= (Button) findViewById(R.id.btn_calc);
mBtnCalc.setOnClickListener(this);
}

@Override
public int getNum1()
{

try{
return Integer.parseInt(mEtNum1.getText().toString());
}
catch (Exception e){
}
return 0;
}

@Override
public int getNum2()
{

try{
return Integer.parseInt(mEtNum2.getText().toString());
}
catch (Exception e){
}
return 0;
}

@Override
public void setCalcResult(int result)
{

mTvResult.setText(result+"");
}

@Override
public void onClick(View v)
{

switch (v.getId()){
case R.id.btn_calc:
{
mPresenter.onClickCalc();
break;
}
default:
break;
}
}
}

Presenter层

写接口类,一般为调用Model和View的方法。

1
2
3
4
5
6
7
8
9
10
11
12
public interface CalcPresenter
{

/**
* 初始化
*/

void onCreate();

/**
* 按钮点击计算
*/

void onClickCalc();
}

写实现类,Presenter持有View与Model的引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CalcPresenterImpl implements CalcPresenter
{

CalcView mView;
CalcModel mModel;

public CalcPresenterImpl(CalcView mView){
this.mView=mView;
mModel=new CalcModelImpl();
}

@Override
public void onCreate()
{

mView.init();
}

@Override
public void onClickCalc()
{

mView.setCalcResult(mView.getNum1()+mView.getNum2());
}
}

运行

总结与思考

关于Presenter持有Model与View的引用,还有View层持有Presenter的思考。这里我觉得可以,将实例化用静态工厂模式的方式来创建实例,会比较好些。