andorid 中 MVP模式 个人理解与运用

andorid 中 MVP模式 个人理解与运用(原创)

原创文章,转载请注明出处!
by–臻宇

前几天阅读了关于MVC模式和MVP模式的文章,文章链接如下:
http://www.uml.org.cn/sjms/201006244.asp
笔者觉得很有意思,于是便想尝试对MVP模式的运用,笔者为了突出MVP模式的重点“怎么将数据(data)从用户接口(view)中分离出来,以及用户接口如何与数据进行交互”简化了一些代码逻辑,望大家不要介意,这里运用的情景是登录,我将尝试着运用MVP模式对登录情景将登录界面(View)与登录逻辑(Model)进行分离,他们通过Presenter进行交互。

界面如图所示:

一个简单的登录界面

既然是MVP模式的运用,自然少不了M(Model),V(View),P(Presenter)这三者:

/**
 * Model 主要任务是处理业务
* Created by Administrator on 2015/8/4.
 */
public interface LoginModel <T>{

/**
     * 处理登录
* @param name
* @param password
* @return
*/
public T login(String name,String password);

}
/**
 * 视图,只要任务在于更新视图
* Created by Administrator on 2015/8/4.
 */
public interface LoginView <T> {

public  void showPreExecute();//更新马上登录前的UI变化,比如添加缓冲条什么的。。

public void showResult(T data);//将结果更新到UI上

public void showProgress(Integer progress);//更新进度

}
/**
 * 控制者 Presenter
 * Created by Administrator on 2015/8/4.
 */
public class Presenter extends AsyncTask<String, Integer, String> {

//模型对象
private LoginModel<Boolean> loginModel;
//视图对象
private LoginView<String> loginView;

public Presenter(LoginView<String> loginView) {

this.loginModel = new LoginTask(); //LoginTask是LoginModel的实现类
this.loginView = loginView; //一般是Activity或者Fragment
}

@Override
protected String doInBackground(String... params)
{
//做了些逻辑处理
if(TextUtils.isEmpty(params[0]) || TextUtils.isEmpty(params[1]))
      {
        return  "用户名或密码不能为空";
      }

if(params[0].length()<6 ||params[0].length()>32)
      {
        return  "用户名不合法";
      }

if(params[1].length()<6 ||params[1].length()>32)
    {
       return  "密码长度不合法";
    }

//吧啦吧啦。。。
// 比如判断网络,检查用户名类型什么之类的一大堆逻辑,
//...........

    //整个登录判断逻辑走完了,接下来正式登录了

for(int i=0;i<100;i++)  //模拟更新进度
{
try
{
   publishProgress(i);//
   Thread.sleep(200);
}catch(InterruptedException e)
  {
   return "登录异常!";
  }
    }

Boolean result = loginModel.login(params[0], params[1]);//模拟登录处理

if(result) return "登录成功";
  else    return "登录失败";
 }

@Override
protected void onProgressUpdate(Integer... values) {
  super.onProgressUpdate(values);
  loginView.showProgress(values[0]);//将新进度更新到UI上
}

@Override
protected void onPostExecute(final String success) {
  loginView.showResult(success);//业务处理好了,更新视图
}

@Override
protected void onPreExecute() {
  super.onPreExecute();

  if(loginView != null)
  loginView.showPreExecute();//更新登录前的UI
 }
}

对于Presenter,笔者只是简单地继承于AsyncTask,目的就是为了做耗时操作,可以看到,在Presenter内部做了许多逻辑处理,如果这些代码放到Actvity中,就会导致代码可读性下降了,处理了业务逻辑后,
Presenter就简单地调用了loginModel进行业务处理,而并不关心loginModel如何处理登录,然后拿到处理结果并通过调用loginView去更新视图,而并不关心loginView如何更新视图。
而且可以很清楚地看到,loginModel与loginView并没有调用或者引用关系,也就是说二者实现了解耦,完全通过Presenter控制二者的交互,应该是符合MVP模式的思想了吧。
接下来再看看,视图与模型的具体实现类吧:

/**
 * 模型的实现类 处理登录请求
* Created by Administrator on 2015/8/4.
 */
public class LoginTask implements  LoginModel<Boolean> {

      String mEmail;
      String mPassword;
@Override
public Boolean login(String name, String password) {
//...耗时的网络请求

//假定登录失败
Boolean result = false ;
return result;
    }
}

这个很简单吧,就是做些网络请求之类的,然后返回数据!

/**
 * 这里Activity实现了LoginView接口,所以充当视图,其代码很简单,就是更新视图
* 这个界面不是笔者写的,只是照搬谷歌的模板。
*/
public class LoginActivity extends Activity implements LoginView<String> {

// UI
private AutoCompleteTextView nameView;
private EditText mPasswordView;
private ProgressBar mProgressView;
private View mEmailLoginFormView;
private View mSignOutButtons;
private View mLoginFormView;

Toast toast;

Presenter presenter; //控制者
@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_login);

nameView = (AutoCompleteTextView) findViewById(R.id.username);

mPasswordView = (EditText) findViewById(R.id.password);

Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
mEmailSignInButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
String name =nameView.getText().toString(); //从UI上获取用户输入
String psw = mPasswordView.getText().toString();

presenter = new Presenter(LoginActivity.this);//创建一个控制者
presenter.execute(name,psw); //将数据提交给presenter,让presenter去处理
}
 });

mLoginFormView = findViewById(R.id.login_form);
mProgressView = (ProgressBar)findViewById(R.id.login_progress);
mEmailLoginFormView = findViewById(R.id.email_login_form);
mSignOutButtons = findViewById(R.id.plus_sign_out_buttons);
 }

@Override
public void showPreExecute() {
showToast("开始请求登录");
mProgressView.setVisibility(View.VISIBLE);
 }

@Override
public void showResult(String data) {
mProgressView.setVisibility(View.GONE);
showToast(data);
}

@Override
public void showProgress(Integer progress) {

mProgressView.setProgress(progress);
    }

void showToast(String s)
    {
if(toast!=null )toast.cancel();
toast = Toast.makeText(this,s,Toast.LENGTH_SHORT);
toast.show();
    }

}
作为一个Actvity,其代码量是很少了吧。可以看到,这个Actvity只做了大致做了三件事:
1.初始化UI;
2.从UI上提取用户输入,并提交给Presenter;
3.被动地更新UI。

所以整个逻辑是很清晰的,作为一个视图,它就负责UI!其实,它也可以是Fragemnt,也可以是别的什么布局,反正就是更新UI,对不,这就是MVP模式的好处啊,改天,我想改变一下进度条的显示效果,或者登陆成后弹出个窗口之类的,可以具体定位到具体的方法里改就好,不需在一大堆逻辑与UI混杂的代码里艰涩的修改。对于Model来说,修改业务代码也是如此。
我这个demo大致就这样了,XML代码很简单,我就不贴出来了,这就是我对MVP模式的理解与运用,也许还有理解不到位的地方,希望大家指出!
另外,这个demo只是为了凸显MVP模式的优点,有些细节并没有处理好,例如使用AsyncTask导致的内存泄露的问题等,请谅解啦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为你解答关于Android MVP模式和使用Kotlin模拟登录的问题。 首先,MVP模式是一种架构模式,它将应用程序分为三个部分:模型(Model),视图(View)和控制器(Presenter)。MVP模式的主要目的是将业务逻辑和用户界面分离,从而实现更好的代码可读性和可维护性。 在Android开发MVP模式通常用于处理复杂的UI和业务逻辑。下面是一个使用Kotlin模拟登录的Android MVP模式示例: 1. 创建一个包含登录逻辑的模型 ```kotlin interface LoginModel { fun login(username: String, password: String, callback: LoginCallback) } interface LoginCallback { fun onSuccess() fun onFailure(error: String) } class LoginModelImpl : LoginModel { override fun login(username: String, password: String, callback: LoginCallback) { // 模拟登录 if (username == "admin" && password == "123456") { callback.onSuccess() } else { callback.onFailure("用户名或密码错误") } } } ``` 2. 创建一个视图接口和一个实现视图接口的Activity ```kotlin interface LoginView { fun showLoading() fun hideLoading() fun showToast(msg: String) } class LoginActivity : AppCompatActivity(), LoginView { private lateinit var presenter: LoginPresenter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) presenter = LoginPresenterImpl(this, LoginModelImpl()) btn_login.setOnClickListener { presenter.login(et_username.text.toString(), et_password.text.toString()) } } override fun showLoading() { // 显示加载 } override fun hideLoading() { // 隐藏加载 } override fun showToast(msg: String) { // 显示Toast } } ``` 3. 创建一个控制器(Presenter)来连接模型和视图 ```kotlin interface LoginPresenter { fun login(username: String, password: String) } class LoginPresenterImpl(private val view: LoginView, private val model: LoginModel) : LoginPresenter { override fun login(username: String, password: String) { view.showLoading() model.login(username, password, object : LoginCallback { override fun onSuccess() { view.hideLoading() view.showToast("登录成功") } override fun onFailure(error: String) { view.hideLoading() view.showToast(error) } }) } } ``` 在此示例,LoginActivity是视图,LoginPresenterImpl是控制器(Presenter),LoginModelImpl是模型。当用户单击“登录”按钮时,LoginActivity将调用LoginPresenterImpl的login方法,该方法将调用LoginModelImpl的login方法进行模拟登录。如果登录成功,LoginPresenterImpl将通知LoginActivity以显示“登录成功”消息;否则,它将通知LoginActivity显示错误消息。 希望这个示例可以帮助你理解Android MVP模式和使用Kotlin模拟登录的实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值