写点什么

Android MVP 模式深入实践探索(一),移动开发工程师简历

用户头像
Android架构
关注
发布于: 刚刚

view接口类中定义的基本都是一些UI数据或者显示UI控件的方法,然让LoginActivity实现这个接口:


public class LoginActivity extends Activity implements ILoginView, View.OnClickListener {


private EditText mUserNameEdit;


private EditText mUserPasswordEdit;


private Button mLoginBtn;


public ProgressDialog mProgressDialog;


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


setContentView(R.layout.activity_login);


initView();


}


private void initView() {


mUserNameEdit = (EditText) findViewById(R.id.edit_user_name);


mUserPasswordEdit = (EditText) findViewById(R.id.edit_user_password);


mLoginBtn = (Button) findViewById(R.id.btn_login);


mLoginBtn.setOnClickListener(this);


}


@Override


public void onClick(View v) {


switch (v.getId()) {


case R.id.btn_login:


//TODO


break;


default:


break;


}


}


@Override


public String getUserName() {


return mUserNameEdit.getText().toString();


}


@Override


public String getUserPassword() {


return mUserPasswordEdit.getText().toString();


}


@Override


public void showToast(String msg) {


ToastUtils.showToast(this, msg);


}


@Override


public void onLoginSuccess() {


ToastUtils.showToast(this, "登录成功");


//跳转首页


gotoHomeActivity();


finish();


}


@Override


public void onLoginFail() {


ToastUtils.showToast(this, "登录失败");


}


@Override


public void showProgressDialog() {


if (mProgressDialog == null) {


mProgressDialog = DialogUtils.showSpinningProgressDialog(this, "正在登录中...", false);


} else {


if (!mProgressDialog.isShowing()) {


mProgressDialog.show();


}


}


}


@Override


public void hideProgressDialog() {


if (mProgressDialog != null) {


mProgressDialog.dismiss();


}


}


@Override


public Context getContext() {


return this;


}


/** 跳转首页 */


private void gotoHomeActivity() {


Intent intent = new Intent(this, MainActivity.class);


startActivity(intent);


}


}


View层到此就完事了,接下来实现PresenterModel角色的接口和实现类


Presenter接口和实现类:


public interface ILoginPresenter {


/** 登录操作逻辑处理 */


void login();


/** 登录成功逻辑处理 */


void onLoginSuccess();


/** 登录失败逻辑处理 */


void onLoginFail(String errMsg);


}


public class LoginPresenter implements ILoginPresenter {


private ILoginView mLoginView;


private ILoginModel mLoginModel;


public LoginPresenter(ILoginView loginView) {


mLoginView = loginView;


mLoginModel = new LoginModelImpl(this);


}


@Override


public void login() {


// 对用户名和密码的校验逻辑,这里只简单判空,实际可以加更多校验


if (TextUtils.isEmpty(mLoginView.getUserName())) {


mLoginView.showToast("请输入用户名");


return;


}


if (TextUtils.isEmpty(mLoginView.getPassword())) {


mLoginView.showToast("请输入密码");


return;


}


//判断网络是否可用


if (!NetUtils.checkNetState(mLoginView.getContext())) {


mLoginView.showToast("当前无网络连接,请检查网络");


return;


}


//显示登录进度弹窗


mLoginView.showProgressDialog();


//调用 model 层发起登录请求


mLoginModel.sendLoginRequest(mLoginView.getUserName(), mLoginView.getPassword());


}


/** 登陆成功 */


@Override


public void onLoginSuccess() {


//隐藏登录进度弹窗


mLoginView.hideProgressDialog();


//回调 View 层接口


mLoginView.onLoginSuccess();


}


/** 登陆失败 */


@Override


public void onLoginFail(String errMsg) {


//隐藏登录进度弹窗


mLoginView.hideProgressDialog();


//回调 View 层接口


mLoginView.onLoginFail(errMsg);


}


}


可以看到在LoginPresenter的实现类当中分别持有了ILoginViewILoginModel两个接口,LoginPresenter通过这两个接口分别与 LoginActivity 和 LoginModel 进行交互。其中ILoginView变量是通过构造函数传递进来的,而ILoginModel则是在构造函数内部创建的。


Model接口和实现类:


public interface ILoginModel {


/** 发起登录请求 */


void sendLoginRequest(String userName, String password);


}


public class LoginModelImpl implements ILoginModel {


private static final String API_LOGIN = "/mobile/login";


priva


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


te ILoginPresenter mPresenter;


public LoginModelImpl(ILoginPresenter mPresenter) {


this.mPresenter = mPresenter;


}


@Override


public void sendLoginRequest(String userName, String password) {


String url = BuildConfig.BASE_IP + API_LOGIN;


StringHashMap requestParams = new StringHashMap();


requestParams.put("userName", userName);


requestParams.put("password", password);


HttpDataManager.post(url, requestParams, new HttpCallback() {


@Override


public void onSuccess(String result, Object tag) {


LoginResultBean loginResult = JsonUtils.jsonToObject(result, LoginResultBean.class);


if (loginResult != null) {


if (loginResult.getErrCode() == 200) {


mPresenter.onLoginSuccess();


} else {


mPresenter.onLoginFail(loginResult.getErrMsg());


}


} else {


mPresenter.onLoginFail("登录失败,服务不可用");


}


}


@Override


public void onError(String result, Object tag) {


mPresenter.onLoginFail("登录失败:"+result);


}


}, 100);


}


}


LoginModelImpl实现类中持有了ILoginPresenter接口,通过它与LoginPresenter实现类进行交户。在LoginModelImpl实现类中发起请求调用的是HttpDataManager类的 post 方法,这个类实际上就是你的网络请求框架组件,这里用的是基于开源库的一个简单封装(内部其实还是用的 OkHttpClient)。


HttpDataManager 类的代码:


public class HttpDataManager {


/** 发起 get 请求 */


public static void get(String url, StringHashMap params, HttpCallback callback, int tag) {


RequestParams requestParams = new RequestParams();


requestParams.setAllStrParams(params);


BaseHttpRequest request = new BaseHttpRequest(url, requestParams, callback, tag);


HttpClient.getInstance().get(request);


}


/** 发起 post 请求 */


public static void post(String url, StringHashMap params, HttpCallback callback, int tag) {


RequestParams requestParams = new RequestParams();


requestParams.setAllStrParams(params);


BaseHttpRequest request = new BaseHttpRequest(url, requestParams, callback, tag);


HttpClient.getInstance().post(request);


}


}



这里建了两个类HttpDataManagerLocalDataManager分别用来管理网络请求和本地数据存取(File、SharePrefer、DataBase),这里你可以使用流行的开源网络请求库或者其他数据管理库(如 Retrofit、GreenDao 等)。当然对于一个好的架构模式不应该受限于这些库,你可以随意选取。


最后就是在 LoginActivity 当中调用 LoginPresenter 的方法进行登录操作了:


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


setContentView(R.layout.activity_login);


mLoginPresenter = new LoginPresenter(this);


initView();


}


@Override


public void onClick(View v) {


switch (v.getId()) {


case R.id.btn_login:


//开始登录


mLoginPresenter.login();


break;


default:


break;


}


}


到此,一个简单登录页面的 MVP 模式的简单实现就完成了。


如果是第一次接触 MVP,你会明显的发现类文件比传统的写法陡增啊!是的,没错,这也是 MVP 的缺点之一,一个页面要想用 MVP 模式做的比较完美至少要建立五、六个 Java 类,因为 Model 层和 Presenter 层要交互,Presenter 层和 View 层要交互,每个交互都需要接口来进行,即便你使用一些依赖注入框架,可能减少 new 对象的代码,但是 Java 类文件数量依然是少不了的,这是由 MVP 的角色和角色职责功能决定的。


所以你可能感觉原来在一个 Activity 当中就能完成的工作,现在要分这么多文件,但是这样做的代价就是换来了业务逻辑的解耦和职责的划分清晰,别忘了我们当初是为了什么目的来用这个模式的!任何一个模式都会有利有弊,有奉献就会有牺牲,你不可能做到只利用它的优点而不接受它的缺点影响。

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android MVP模式深入实践探索(一),移动开发工程师简历