mvp菜鸟级入门教程

mvp菜鸟级入门教程

对于入门mvp的话,我觉得越简单越好,不应该是多复杂多高大上的东西,毕竟咱们搞技术的也都实在,mvp对于开发商业项目的开发很有帮助,我以前写的都是mvc的代码,写完之后很臃肿,同事见了痛苦不堪,mvp的好处就是能够实现代码分离,不会一个activity里面写成千上万代码,而且不好维护和扩展。

  • 1 用mvc写的登录操作。
  • 2 改造成mvp框架形式。
  • 3 使用mock单元测试。

mvc样式

只是为了理解mvp,所以布局文件不贴了。
LoginActivity.java

/**
 * Created by Gorills on 2017/1/15.
 */

public class LoginActivity extends Activity implements View.OnClickListener {
    private final String TAG = LoginActivity.class.getSimpleName();
    EditText usernameTextView, passwordTextView;
    ProgressBar progressBar;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        initView();
    }

    private void initView() {
        progressBar = (ProgressBar) findViewById(R.id.progress);
        usernameTextView = (EditText) findViewById(R.id.username);
        passwordTextView = (EditText) findViewById(R.id.password);
        findViewById(R.id.button).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        String username = usernameTextView.getText().toString();
        String password = passwordTextView.getText().toString();

        if (username.isEmpty() || password.isEmpty()) {
            Toast.makeText(LoginActivity.this, "用户名密码不能为空", Toast.LENGTH_SHORT).show();
        } else if (username.length() < 8 || passwordTextView.length() < 9) {
            usernameTextView.setError("账号至少8位,密码至少9位");
        } else if (username.equals(MainActivity.USERNAME)) {
            if (password.equals(MainActivity.PASSWORD)) {
                // 登录成功,main拨打loginSuccess()电话通知主人登录成功了
                startActivity(new Intent(LoginActivity.this, MainActivity.class));
            } else {
                // 登录失败,main拨打loginFailed()电话通知主人登录失败了,并告知失败原因
                passwordTextView.setError("密码错误");
            }
        }
    }


}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    public static final String USERNAME = "username";
    public static final String PASSWORD = "password";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

以上便是最简单的登录模块了,接下来我们改成使用mvp编写。
LoginActivity.java

**
 * Created by Gorills on 2017/1/15.
 */

public class LoginActivity extends Activity implements LoginView, View.OnClickListener {
    private final String TAG = LoginActivity.class.getSimpleName();
    EditText usernameTextView, passwordTextView;
    ProgressBar progressBar;
    private LoginPresenter loginPresenter;//ctrl+alt+f转换为全局变量

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        initView();
        loginPresenter = new LoginPresenter(this, new LoginService());
    }

    private void initView() {
        progressBar = (ProgressBar) findViewById(R.id.progress);
        usernameTextView = (EditText) findViewById(R.id.username);
        passwordTextView = (EditText) findViewById(R.id.password);
        findViewById(R.id.button).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        loginPresenter.performLoginClick();
    }


    @Override
    public String getUsername() {
        return usernameTextView.getText().toString();
    }

    @Override
    public void showUsernameError(int username_error) {
        usernameTextView.setError(getString(username_error));
    }

    @Override
    public String getPassword() {
        return passwordTextView.getText().toString();
    }

    @Override
    public void showPasswordError(int password_error) {
        passwordTextView.setError(getString(password_error));
    }

    @Override
    public void startMainActivity() {
        // 登录成功,main拨打loginSuccess()电话通知主人登录成功了
        startActivity(new Intent(LoginActivity.this, MainActivity.class));
    }

    @Override
    public void showProgress() {
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideProgress() {
        progressBar.setVisibility(View.GONE);
    }

    @Override
    public void showLoginError(int login_failed) {
        Toast.makeText(LoginActivity.this, getString(login_failed), Toast.LENGTH_SHORT).show();
    }
}

LoginPresenter.java

**
 * Created by Gorills on 2017/1/17.
 */

public class LoginPresenter {//ctrl+shift+t to create test

    private final LoginView loginView;
    private final LoginService loginService;

    public LoginPresenter(LoginView loginView, LoginService loginService) {
        this.loginView = loginView;
        this.loginService = loginService;
    }

    public void performLoginClick() {
        String username = loginView.getUsername();
        if (username.isEmpty()) {
            loginView.showUsernameError(R.string.username_error);
            return;
        }

        String password = loginView.getPassword();
        if (password.isEmpty()) {
            loginView.showPasswordError(R.string.error_incorrect_password);
            return;
        }

        loginView.showProgress();
        boolean succeed = loginService.login(username, password);
        loginView.hideProgress();
        if (succeed) {
            loginView.startMainActivity();
            return;
        } else {
            loginView.showLoginError(R.string.login_failed);
            return;
        }
    }
}

LoginService.java

/**
 * Created by Gorills on 2017/1/17.
 */

public class LoginService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public boolean login(String username, String password) {
        if (username.equals(MainActivity.USERNAME) && password.equals(MainActivity.PASSWORD))
            return true;
        return false;
    }
}

LoginView.java

/**
 * Created by Gorills on 2017/1/17.
 */

public interface LoginView {
    String getUsername();

    void showUsernameError(int username_error);


    String getPassword();

    void showPasswordError(int password_error);

    void startMainActivity();

    void showProgress();

    void hideProgress();

    void showLoginError(int login_failed);
}

这样看起来虽然代码并没有减少,但是在LoginActivity里面看到的代码逻辑明显变清晰了,他只需要处理界面相关的代码,功能代码放在了Presenter里面。

使用Mockito对Demo进行测试

notes:因为以前很少用junit测试,所以在摸索中卡在了一个地方,我是参照youtube上的一个教程做的,检查了好几遍也没找到问题出在哪里。

Process finished with exit code 1
Class not found: “com.zzz.login.LoginPresenterTest”Empty test suite.

后面才发现是在清单文件里面没有配置,我们需要在清单文件里面添加

import com.gorills.testmvp.R;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

/**
 * Created by Administrator on 2017/1/18.
 */
@RunWith(MockitoJUnitRunner.class)
public class LoginPresenterTest {

    @Mock
    private LoginView loginView;
    LoginPresenter loginPresenter;

    @Before
    public void setUp() throws Exception {
        loginPresenter = new LoginPresenter(loginView);
    }

    @Test
    public void showLoginErrorWhenPasswordEmpty() {
        when(loginView.getUsername()).thenReturn("username");
        when(loginView.getPassword()).thenReturn("");
        loginPresenter.doLogin();
        verify(loginView).showPasswordError(R.string.password_empty);
    }

    @Test
    public void showLoginErrorWhenUsernameEmpty() {
        when(loginView.getUsername()).thenReturn("");
        loginPresenter.doLogin();
        verify(loginView).showUsernameError(R.string.username_empty);
    }



    @org.junit.Test
    public void testShowErrorWhenLoginError() throws Exception {
        when(loginView.getUsername()).thenReturn("USERNAME");
        when(loginView.getPassword()).thenReturn("PASSWORK");
        loginPresenter.doLogin();
        verify(loginView).showLoginError();
    }


}

这里就算一个demo入门啦,当然mvp远不止这些后面还有很多,我在学习的途中会陆续贴出我的学习笔记供大家参考。写的不对麻烦指出,有疑问欢迎留言。

源码下载
http://download.csdn.net/detail/zhonglunshun/9741065

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯人院的院长大人

给点实际性的支持不?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值