原文链接:链接
今天仔细的研究了一下这篇文章,感觉原作者写的很不错,条例也很清晰。
但是,给的例子相对来说有点容易让人摸不着头脑。
我在他的例子的基础上进行了一些修改,并且加上了一些我的个人理解。
MVP架构的重要了,理念就是把View层与业务逻辑层给相互独立并抽象了出来。
简化了Activity的代码量。同时也让各逻辑层的功能更加凸显。
下面正式开始:
这个是MVP的架构图:
首先让大家看一下我的项目文件组织结构:
activity:存放activity类
bean:存放对象类
callback:存放回调函数接口
model:存放业务逻辑有关的接口以及其实现类
presenter:存放view与model的转发层有关类
view:存放抽象的view层接口
下面,我们按照业务逻辑的顺序进行讲解:
View层是以接口的形式定义,我们不关心数据,不关心逻辑处理,只关心和用户的交互。
我们把View层的抽象为IUserLoginView接口。
在这个接口中,我们需要定义数据获取的方法,以便Presenter获取View的数据。
还需要定义对View组件进行有关操作的方法,以便Presenter获取数据后进行相关的状态显示,增强与用户的交互感。
/**
* View层是以接口的形式定义
* 我们不关心数据
* 不关心逻辑处理
* 只关心和用户的交互
*/
public interface IUserLoginView {
//接口中需要定义参数传递的方法
//以及对View进行有关操作的方法
String getUserName();
String getPassword();
void showLoading();
void hideLoading();
void toMainActivity(User user);
}
Activity是View层的一部分,所以其需要实现上边所抽象的View层接口,以便Presenter层对其数据进行获取(通过调用其接口所定义的数据获取方法)。
Activity内还需要实例化一个UserLoginPresenter对象,以便其内部的有关事件能够调用其对应的业务处理转发的Presenter层
/**
* Activity类View层的接口
*/
public class MainActivity extends AppCompatActivity implements IUserLoginView {
private EditText mEtUsername, mEtPassword;
private Button mBtnLogin, mBtnClear;
private ProgressBar mPbLoading;
//实例化该View所需要的业务处理转发Presenter层,以便能够进行回调
private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
//获取前端组件
mBtnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//将View层的用户输入,传递到业务转发Presenter层进行处理
mUserLoginPresenter.login();
}
});
}
@Override
public String getUserName() { return mEtUsername.getText().toString(); }
@Override
public String getPassword() { return mEtPassword.getText().toString(); }
@Override
public void showLoading() { mPbLoading.setVisibility(View.VISIBLE); }
@Override
public void hideLoading() { mPbLoading.setVisibility(View.GONE); }
@Override
public void toMainActivity(User user) {
Toast.makeText(this, user.getUserName() +
" login success , to MainActivity", Toast.LENGTH_SHORT).show();
}
Presenter的作用就是从View层获取用户的输入, 传递到Model层进行处理, 然后回调给View层,输出给用户。
这几个步骤对应了不同的操作:
1、获取View层对象以及Model层对象:对应的是该Presenter的构造方法。
2、进行业务转发。
3、回调函数通过调用View层的相关方法将处理后的结果返回。
其中业务转发中包含了回调函数接口的实例化(对应的是new OnLoginListener(){})。
/**
* Presenter的作用就是从View层获取用户的输入
* 传递到Model层进行处理
* 然后回调给View层
* 输出给用户
*/
public class UserLoginPresenter {
private IUserBiz userBiz;//初始化Model的接口
private IUserLoginView userLoginView;//初始化View接口
private Handler mHandler = new Handler();
//Presenter拿到View和Model的实现类,以便进行业务逻辑处理数据的传输
public UserLoginPresenter(IUserLoginView userLoginView) {
//获取View层的实现类
this.userLoginView = userLoginView;
//获取Model层的实现类
this.userBiz = new UserBiz();
}
//执行业务转发的方法
public void login() {
//操作View层相关的状态显示方法
userLoginView.showLoading();
//传递数据到Model层进行处理
//new OnLoginListener(){}用来实例化接受回调的函数
userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {
@Override
public void loginSuccess(final User user) {
//需要在UI线程执行
mHandler.post(new Runnable() {
@Override
public void run() {
userLoginView.toMainActivity(user);
userLoginView.hideLoading();
}
});
}
});
}
}
处理结果回调,我们抽象出来成为接口。
/**结果回调接口*/
public interface OnLoginListener {
void loginSuccess(User user);
}
我们将业务处理逻辑抽象成为接口。
其方法中应该添加View层回调函数参数。
/**定义业务接口*/
public interface IUserBiz {
/**
* 业务处理方法
* 该方法需要定义数据参数及回调函数参数
* @param username 业务处理数据参数
* @param password 业务处理数据参数
* @param loginListener 回调函数参数
*/
void login(String username, String password, OnLoginListener loginListener);
}
实现有关业务处理逻辑接口。
/**Model层处理*/
public class UserBiz implements IUserBiz {
@Override
public void login(final String username, final String password, final OnLoginListener loginListener){
//进行相关业务处理
User user = new User();
user.setUserName(username);
user.setPassword(password);
//结果回调
loginListener.loginSuccess(user);
}
}
经过这样分解,整个项目结构就更加的清晰了。