android架构之mvp

上一节mvc的案例中,可以发现,view可以直接访问model,这样就耦合性比较高,需要优化,这时候出现了升级版的mvc之mvp

下面以用户登录为例子


1.preseter接口

/**
 * Presenter 接口
 * @author smile
 */

public interface ILoginPresenter {
    /**
     * 登录
     * */
    void login(String account,String pwd);
    /**
     * 登录成功
     * */
    void loginSucess(String msg);
    /**
     * 登录失败
     * */
    void loginFail(String error);
}

2.model接口

/**
 * model接口
 * @author smile
 */

public interface ILoginModelInterface {
    /**
     * 登录
     * @param account
     * @param pwd
     * */
    void login(String account,String pwd);
}

3.view 接口

/**
 * view接口实例类
 * @smile
 */

public interface IView {
    /**
     * 登录成功
     * @param indicator
     * */
    void loginSucess(String indicator);
    /**
     * 登录失败
     * @param errorMsg
     * */
    void loginFailure(String errorMsg);

}

3.view的实现类activity

/**
 *   mvp demo
 *   view 对应的是视图,事件的来源和产生数据,
 *   持有presenter的实例
 *
 * */

public class MainActivity extends AppCompatActivity implements IView,
        View.OnClickListener{
    private EditText mEdtAccount;
    private EditText mEdtPwd;
    private Button mBtnLogin;
    private TextView mTvResult;
    private ILoginPresenterImpl mILoginPresenter;

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

    private void init() {
        mILoginPresenter=new ILoginPresenterImpl(this);
    }

    private void initEvent() {
        mBtnLogin.setOnClickListener(this);
    }

    private void initView() {
        mEdtAccount=findViewById(R.id.edt_account);
        mEdtPwd=findViewById(R.id.edt_pwd);
        mBtnLogin=findViewById(R.id.btn_login);
        mTvResult=findViewById(R.id.tv_result);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_login:

                String account = mEdtAccount.getText().toString().trim();
                String pwd = mEdtPwd.getText().toString().trim();
                //通过presenter,将数据传递给model进行处理
                mILoginPresenter.login(account,pwd);
                break;
        }
    }

    /**
     * 登录成功的回调函数
     * @param indicator
     * */
    @Override
    public void loginSucess(String indicator) {
        mTvResult.setText(indicator);
    }

    /**
     * 登录失败的回调函数
     * @param errorMsg
     * */
    @Override
    public void loginFailure(String errorMsg) {
        mTvResult.setText(errorMsg);
    }
}

4.presenter的实现类

/**
 * Presenter实现类,持有modelview的实例
 */

public class ILoginPresenterImpl implements ILoginPresenter{
    private LoginModelImpl mLoginModel;
    private IView mIView;

    public ILoginPresenterImpl(IView IView) {
        mIView = IView;
        mLoginModel=new LoginModelImpl(this);
    }

    @Override
    public void login(String account, String pwd) {
        mLoginModel.login(account,pwd);
    }

    /**
     * model 通过preseter回调过来的登录成功函数
     * **/
    @Override
    public void loginSucess(String msg) {
        mIView.loginSucess(msg);
    }
    /**
     * model 通过preseter回调过来的登录失败的函数
     * **/
    @Override
    public void loginFail(String error) {
        mIView.loginFailure(error);
    }

}

5.model的实现类

/**
 * model的实现类,持有presenter的实例
 */

public class LoginModelImpl implements ILoginModelInterface{
    private ILoginPresenterImpl mILoginPresenter;

    public LoginModelImpl(ILoginPresenterImpl ILoginPresenter) {
        mILoginPresenter = ILoginPresenter;
    }

    @Override
    public void login(String account, String pwd) {
        if(TextUtils.isEmpty(account)){
        // 账户不对
            mILoginPresenter.loginFail("账户不能为空");
            return;
        }
        if(TextUtils.isEmpty(pwd)){
            //密码不正确
            mILoginPresenter.loginFail("密码不能为空");
            return;
        }
        if(!TextUtils.equals("zhangsan",account)){
            mILoginPresenter.loginFail(" 账户不对");
            return;
        }
        if(!TextUtils.equals("123",pwd)){
            mILoginPresenter.loginFail("密码不正确");
            return;
        }

        if(TextUtils.equals("zhangsan",account) && TextUtils.equals("123",pwd)){
            //登录成功
//            通过presenter将处理的结果回传给view(Activity)
             mILoginPresenter.loginSucess("登录成功");
        }

    }
}

思路很简单,其实就是利用接口回调达到分层的目的,在页面的业务比较复杂的或者团队合作的大型项目,mvp的优势特别明显。

源代码:http://download.csdn.net/download/oneblue123/10259289

注意:mvp内存泄漏问题

Presenter中持有View接口对象,这个接口对象实际为MainActivity.this,Modle中也同时拥有Presenter对象实例,当MainActivity要销毁时,Presenter中有Modle在获取数据,那么问题来了,这个Activity还能正常销毁吗?
答案是不能!
当Modle在获取数据时,不做处理,它就一直持有Presenter对象,而Presenter对象又持有Activity对象,这条GC链不剪断,Activity就无法被完整回收。
换句话说:Presenter不销毁,Activity就无法正常被回收。
解决MVP的内存泄露
Presenter在Activity的 onDestroy方法回调 时执行资源释放操作,或者在Presenter引用View对象时使用更加容易回收的软引用,弱应用。
比如示例代码:
Activity
@Override public void onDestroy() { super.onDestroy(); mPresenter.destroy(); mPresenter = null; }

Presenter
public void destroy() { view = null; if(modle != null) { modle.cancleTasks(); modle = null; }}

Modle
public void cancleTasks() { // TODO 终止线程池ThreadPool.shutDown(),AsyncTask.cancle(),或者调用框架的取消任务api}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值