面试Android技术研究Android资料

最简MVP框架

2016-08-08  本文已影响9934人  ed407c8602e0

前言

听到一些童鞋抱怨MVP,所有搞了个辅助实现MVP的小东西,叫MvpFrame。还不了解MVP的先看《Google原味mvp实践》。主要的功能如下

开源地址是

https://github.com/wolearn/MvpFrame

怎么用

可以把上面工程中的mvpframelib作为Android Lib引入,或者直接复制java文件也可以。我简单解释下还是我常用那个登陆的例子。先看目录结构。


初始化

在Application中调用

Mvp.getInstance().init(this);

规划好view和presenter的接口。

public class LoginContract {
    public interface View extends BaseView {
        String getAccount();
        String getPassword();
        void loginSuccess();
        void loginError(String errorMsg);
    }

    public interface Presenter extends BasePresenter {
        void login();
    }
}

用一个契约类来定义需要的方法。之前有童鞋问我,这个接口写好烦,能不能不写。肯定不能。我能想到的理由有三点

View层

可以支持Activity和Fragment,Activity继承MvpActivity,Fragment继承MvpFragment。

public class LoginActivity extends MvpActivity<LoginPresenter> implements LoginContract.View, View.OnClickListener {
    private EditText edtAccount, edtPassword;
    private Button btnLogin;

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

        initViews();
    }

    @Override
    public BaseView getBaseView() {
        return this;
    }

    @Override
    public void onClick(View v) {
        mPresenter.login();
    }

    private void initViews() {
        edtAccount = (EditText) findViewById(R.id.edt_account);
        edtPassword = (EditText) findViewById(R.id.edt_password);
        btnLogin = (Button) findViewById(R.id.btn_login);

        btnLogin.setOnClickListener(this);
    }

    @Override
    public void loginError(String msg) {
        Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void loginSuccess() {
        Toast.makeText(LoginActivity.this, getResources().getString(R.string.login_success), Toast.LENGTH_SHORT).show();
    }

    @Override
    public String getAccount() {
        return edtAccount.getText().toString();
    }

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

Presenter层

Presenter继承MvpPresenter实现即可。

public class LoginPresenter extends MvpPresenter<LoginHttp, LoginContract.View> implements LoginContract.Presenter {
    private static final String TAG = "LoginPresenter";

    @Override
    public void login() {
        if (!checkParameter()) return;

        String account = getIView().getAccount();
        String password = getIView().getPassword();

        mModel.login(account, password);

        //模拟登陆成功
        getIView().loginSuccess();
    }

    /**
     * 登录参数校验
     *
     * @return
     */
    private boolean checkParameter() {
        try {
            if (TextUtils.isEmpty(getIView().getAccount())) {
                getIView().loginError(mContext.getString(R.string.toast_account_empty));
                return false;
            }

            if (TextUtils.isEmpty(getIView().getPassword())) {
                getIView().loginError(mContext.getString(R.string.toast_password_empty));
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}

Model层

数据的来源一般有三个:DB,NET,Cache。看个图



之前有童鞋说,业务过程很烦,要搞个UseCase文件,然后又要搞个Repository文件,最后搞个HttpLogin,因为登录本来就只是要跟服务端确认,前面2个文件基本都是透传。是不是一定要这么死板呢?当然不是,结构可以根据业务的复杂度做调整的。比如我这里登录就是直接让HttpLogin继承MvpModel, 直接跟P层交互。

public class LoginHttp extends MvpModel {
    private static final String TAG = "LoginHttp";

    /**
     * 密码登陆
     *
     * @param account
     * @param password
     */
    public void login(String account, String password) {
//        execute(api.login(account, password), callback);
    }
}

如果你当前业务是只跟DB打交道,也可以让LoginDB继承MvpModel,然后在P层的泛型中确认类型即可。

其他任意位置获取M,V,P实例

默认通过以下API获取的唯一实例,传入为实例的class类型

Mvp.getInstance().getPresenter();
Mvp.getInstance().getModel();
Mvp.getInstance().getView();

getPresenter 和 getModel 的实例默认会创建,getView 要确定Activity或者Fragment已经创建,否则可能为null。

后记

建议以文件的形式引入,方便依据工程业务做定制化。喜欢请帮忙戳喜欢,有问题欢迎评论。

日志(记录一些issue和优化点)

1.关于P层Login方法参数是通过IView来获取还是直接login(String account, String password),就当前登录的例子来说,直接通过方法传递比较好。

关注我(微信扫一扫)

上一篇下一篇

猜你喜欢

热点阅读