对此题目有兴趣的同学都是知道至少了解这个东西,在此我不准备讲太多的理论,因为互联网上对MVP的介绍铺天盖地了.例如这位同学的文章就很精彩 Android MVP 详解(上),本人只是介绍两种MVP在Android的实现方法。
第一种:MVP在Android中2种实现(1)
第二种: MVP在Android中2种实现(2)
第一种
众所周知,MVP全称 Model-View-Presenter
Model:负责提供数据,转化为目标格式供上层接口调用
View:负责内容显示及操作指令下发
Presenter:负责协调View和Model
首先,由于大部分Android APP只是一个客户端,具体的业务逻辑几乎都在后台服务器,所以此处降低了Model的职责,将从后台获取数据写在了Presenter里面,特此说明。
本例以开发一个登陆功能来说明
具体实现思路如下:
我们知道要针对抽象编程,所以先设计接口:此处我们需要两个接口,第一个是业务逻辑接口表示登录这个操作,让presenter实现。第二个是View要实现的接口,表示View要针对登录这个操作返回的结果做出响应。
presenter实现的接口Login1Presenter
package com.ss007.androidmvpsample.mvp;
/**
* Copyright (C) 2017
*
*
* @author ben
* @version 1.0
* @createDate 2017/7/5 10:30
* @description
*/
public interface Login1Presenter
{
void login(String userName,String passWord);
}
View实现的接口Login1ActView
package com.ss007.androidmvpsample.mvp;
/**
* Copyright (C) 2017
*
*
* @author ben
* @version 1.0
* @createDate 2017/7/5 10:29
* @description
*/
public interface Login1ActView
{
void loginSuccess(String responseStr);
void loginFailed(String code,String errBody);
}
Model
省略
View
View 自然就让我们的Activity来充当了,命名为Login1Act,样子如下图
负责参数输入,指令触发(登录),对处理结果及时作出响应
package com.ss007.androidmvpsample.mvp;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.ss007.androidmvpsample.BaseActivity;
import com.ss007.androidmvpsample.R;
public class Login1Act extends BaseActivity implements Login1ActView
{
private final static String TAG = Login1Act.class.getSimpleName();
private EditText userName, passWord;
private Button btnLogin;
private Login1Presenter mPresenter;
private Activity mAct;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login1);
mAct = this;
userName = (EditText) findViewById(R.id.et_user_name);
passWord = (EditText) findViewById(R.id.et_password);
btnLogin = (Button) findViewById(R.id.btn_login);
btnLogin.setOnClickListener(clickListener);
mPresenter = new Login1PresenterImp(this);
}
@Override
public void loginSuccess(String responseStr)
{
btnLogin.setText("Login");
Log.d(TAG, String.format("result: %s", responseStr));
Toast.makeText(mAct, "login success", Toast.LENGTH_SHORT).show();
}
@Override
public void loginFailed(String code, String errBody)
{
Log.d(TAG, String.format("error code:%s | error body: %s", code, errBody));
Toast.makeText(mAct, "login failed", Toast.LENGTH_SHORT).show();
}
private View.OnClickListener clickListener = new View.OnClickListener()
{
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.btn_login:
if (mPresenter != null)
{
btnLogin.setText("Loginning ...");
mPresenter.login(userName.getText().toString(), passWord.getText().toString());
}
break;
default:
break;
}
}
};
}
Presenter
负责向后台发起网络请求
package com.ss007.androidmvpsample.mvp;
import android.os.Handler;
/**
* Copyright (C) 2017
*
*
* @author ben
* @version 1.0
* @createDate 2017/7/5 10:30
* @description
*/
public class Login1PresenterImp implements Login1Presenter
{
private Login1ActView login1ActView;
public Login1PresenterImp(Login1ActView login1ActView)
{
this.login1ActView=login1ActView;
}
@Override
public void login(String userName, String passWord)
{
//模拟登录(Mock login)
new Handler().postDelayed(new Runnable()
{
@Override
public void run()
{
boolean isSuccess=true;//根据实际情况判断
if (login1ActView==null)
return;
if (isSuccess)
{
login1ActView.loginSuccess("the result get from your server");
}
else
{
login1ActView.loginFailed("error code","error body");
}
}
}, 2000);
}
}
代码已经非常简单明了了,在此我做一点讲解:
第一步:根据业务需要定义两个接口,一个给Presenter实现,一个给View实现。
第二步:如果决定使用轻Model重Presenter的模式,那么Model基本就是一些JavaBean
类,让View持有Presenter的引用(最好是以接口声明),那么在View中就可以调用Presenter里面的方法了,例如点击登录按钮,调用presenter里面的login()
方法。
第三步:Presenter里面的方法执行后会有结果回来,那么View是要对这些结果做出响应的,例如登录后是成功了还是失败了呢?这就需要从Presenter里面调用View里面的方法将结果传过去。所以需要Presenter持有一个View的引用(最好是以接口声明)。
小结
这种方法的优点就是简单,但是有一个比较严重的问题就是在一定的情况下会造成内存泄漏。
例如这个登录页面没有一个不可取消的loading弹窗,那么用户就可以随时关闭登录页面,那么由于Presenter持有View的引用,而又当Presenter有未完成的操作不能被GC回收时,Activity也不能够释放,就会造成内存泄漏。
第二种方法将会讲解如何改进第一种方法,避免内存泄漏。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/14807.html