Android MVP登录小例子
2018-07-24 本文已影响10人
wmjwmj
1. MVP简介略
1.1 Model
业务逻辑。如访问网络、数据库
实体类
1.2 View
该页面的逻辑,需要做什么动作,反馈,交互等
1.3 Presenter
负责View和Model的交互
2. 登录模块例子
LoginModel为登录的网络操作。略
2.1 LoginView接口
抽象登录页面需要的一些逻辑
public interface LoginView {
/**
* 获取用户名称
*/
String getUserName();
/**
* 获取用户密码
*/
String getPassword();
/**
* 处理登录结果
*/
void onLoginResult(String result);
}
2.2 LoginActivity
实现LoginView接口。持有LoginPresenter的引用
public class LoginActivity extends AppCompatActivity implements LoginView {
@BindView(R.id.et_username)
EditText mEtUsername;
@BindView(R.id.et_password)
EditText mEtPassword;
// 持有LoginPresenter的引用
private LoginPresenter mLoginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
}
@Override
public String getUserName() {
return mEtUsername.getText().toString();
}
@Override
public String getPassword() {
return mEtPassword.getText().toString();
}
@Override
public void onLoginResult(String result) {
// 处理登录结果
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
}
});
}
@OnClick(R.id.btn_login)
public void onViewClicked() {
}
}
2.3 LoginPresenter
持有LoginView接口的引用,持有LoginModel的引用。构造函数传入view,实例化model。根据LoginModel提供登录方法
public class LoginPresenter {
// 持有LoginView接口的引用
private LoginView mLoginView;
// 持有LoginModel的引用
private LoginModel mLoginModel;
// 传入LoginView
public LoginPresenter(LoginView loginView) {
mLoginView = loginView;
// 实例化LoginModel
mLoginModel = new LoginModel();
}
/**
* 登录
*/
public void login(){
mLoginModel.login(mLoginView.getUserName(), mLoginView.getPassword(), new LoginCallback() {
@Override
public void onLoginResult(String result) {
if (null != mLoginView) {
// 回调到UI层
mLoginView.onLoginResult(result);
}
}
});
}
}
2.4 回到LoginActivity
实例化LoginPresenter,传入this。实现登录方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
// 实例化LoginPresenter
mLoginPresenter = new LoginPresenter(this);
}
@OnClick(R.id.btn_login)
public void onViewClicked() {
mLoginPresenter.login();
}
3.优化
3.1 Presenter一直持有View的引用,如何解除?
LoginPresenter提供绑定View和解绑View的方法
public class LoginPresenter {
// 持有LoginView接口的引用
private LoginView mLoginView;
// 持有LoginModel的引用
private LoginModel mLoginModel;
public LoginPresenter() {
// 实例化model
mLoginModel = new LoginModel();
}
/**
* 绑定View
*/
public void attachView(LoginView loginView){
mLoginView = loginView;
}
/**
* 解绑View
*/
public void detachView(){
mLoginView = null;
}
···
}
LoginActivity在onCreate()中绑定View,在onDestroy中解绑View
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
// 实例化LoginPresenter
mLoginPresenter = new LoginPresenter();
// 绑定
mLoginPresenter.attachView(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 解绑
mLoginPresenter.detachView();
}
3.2 多个Presenter,都要写绑定和解绑的方法,如何复用?把绑定和解绑的方法封装到父类,LoginView写死了怎么办?
BasePresenter持有View的引用,类型是泛型。封装绑定View和解绑View的方法
public class BasePresenter<V extends BaseView> {
private V mView;
public V getView() {
return mView;
}
/**
* 绑定View
*/
public void attachView(V view){
mView = view;
}
/**
* 解绑View
*/
public void detachView(){
mView = null;
}
}
- 3 多个Activity,都要写绑定和解绑的方法,如何复用?
BaseActivity持有View和Presenter的引用。提供抽象方法让其子类实例化View和Presenter。onCreate()中绑定View,调用抽象方法,onDestroy()中解绑View。BaseFragment、BaseListView等同理
public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V>> extends AppCompatActivity{
// 持有View的引用
private V mView;
// 持有Presenter的引用
private P mPresenter;
public P getPresenter() {
return mPresenter;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (null == mView) {
mView = createView();
}
if (null == mPresenter) {
mPresenter = createPresenter();
}
if (null == mView) {
throw new NullPointerException("view can not be null!");
}
if (null == mPresenter) {
throw new NullPointerException("presenter can not be null!");
}
// 绑定view
mPresenter.attachView(mView);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 解绑view
mPresenter.detachView();
}
/**
* 创建view
*/
public abstract V createView();
/**
* 创建presenter
*/
public abstract P createPresenter();
}
public class LoginActivity extends BaseActivity<LoginView, LoginPresenter> implements LoginView{
@BindView(R.id.et_username)
EditText mEtUsername;
@BindView(R.id.et_password)
EditText mEtPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
}
@Override
public LoginView createView() {
return this;
}
@Override
public LoginPresenter createPresenter() {
return new LoginPresenter();
}
@Override
public String getUserName() {
return mEtUsername.getText().toString();
}
@Override
public String getPassword() {
return mEtPassword.getText().toString();
}
@Override
public void onLoginResult(final String result) {
// 处理登录结果
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
}
});
}
@OnClick(R.id.btn_login)
public void onViewClicked() {
getPresenter().login();
}
}