MVP在Android中2种实现(1)

导读:本篇文章讲解 MVP在Android中2种实现(1),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

对此题目有兴趣的同学都是知道至少了解这个东西,在此我不准备讲太多的理论,因为互联网上对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实现。
第二步:如果决定使用轻ModelPresenter的模式,那么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

(0)
小半的头像小半

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!