Android MVP-编程思想5(如何处理多个P层的问题?)

Posted 0 and 1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android MVP-编程思想5(如何处理多个P层的问题?)相关的知识,希望对你有一定的参考价值。

前言

通过一个小的登录功能模块案例,帮助大家了解MVP。最终实现一个结合Rxjava2,Retrofit 的MVP通用框架。代码放到github上。(如有错误之处,请在评论区指出,谢谢。如果感觉写的不错,请点赞,关注,谢谢。)

目录:

Android MVP-编程思想1(什么是MVC-MVP-MVVM模式?)
Android MVP-编程思想2(代码实现初级版)
Android MVP-编程思想3(内存泄露问题处理,基类封装,有没有必要再使用软引用?)
Android MVP-编程思想4(AOP思想-动态代理运用,反射创建M层实例对象)
Android MVP-编程思想5(如何处理多个P层的问题?)
Android MVP-编程思想6(依赖注入多个P层优化—注解,反射)
Android MVP-编程思想7(为什么使用代理类抽取通用方法而不是工具类?,基类BaseMvpFragment)

未完待续--------
android MVP-编程思想8(集成Rxjava2,Retrofit)

实际开发中,当业务相对复杂的应用,我们的 Presenter 层并不是只一个,会存在View 与 Presener 层的一对多的关系。显示之前的代码设计不能满足这种需求。

回顾一下之前的设计(一对一)

之前是在BaseMvpActivity 中持有P层的引用(当时假设只有一个),BaseMvpActivity提供了createPresenter抽象方法,让子类实现. 通过这种方式注入P的实例对象。

如何处理一(V)对多(P)

聪明的读者很容易想到,多个P的引用用一个容器装起来就可以,抽象方法createPresenter() 原来返回一个P,现在让它返回多个就OK了。看代码

BaseMvpActivity 去除泛型参数

因为是多个P,所以使用容器存储P层引用

protected List<? extends BasePresenter> mPresenters;

相应的抽象方法的返回参数变成

protected abstract List<? extends BasePresenter> createPresenter()

子类实现的时候,将多个P放入容器返回就可以了

 @Override
    protected List<? extends BasePresenter> createPresenter() 
        ArrayList<BasePresenter> presenters = new ArrayList();
        loginPresenter = new LoginPresenter();
        presenters.add(loginPresenter);
        return presenters;
    

然后是注入V的改动

for (BasePresenter p : mPresenters) 
            p.attachView(this);
 

释放V的改动

   for (BasePresenter p : mPresenters) 
            p.detachView();
        
        mPresenters.clear();
        mPresenters = null;

改动之后的代码如下

public abstract class BaseMvpActivity extends AppCompatActivity 
    protected List<? extends BasePresenter> mPresenters;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        View rootView;
        final Object layout = getLayout();
        if (layout instanceof Integer) 
            rootView = View.inflate(this, (int) getLayout(), null);
         else if (layout instanceof View) 
            rootView = (View) getLayout();
         else 
            throw new ClassCastException("type of setLayout() must be int or View!");
        
        setContentView(rootView);
        mPresenters = createPresenter();
        for (BasePresenter p : mPresenters) 
            p.attachView(this);
        

        afterCreate();
    

    @Override
    protected void onDestroy() 
        super.onDestroy();
        for (BasePresenter p : mPresenters) 
            p.detachView();
        
        mPresenters.clear();
        mPresenters = null;
    


    @SuppressWarnings("ConstantConditions")
    protected <T extends View> T $(@IdRes int viewId) 
        return findViewById(viewId);
    

    public void showProgress(boolean isShow) 
        if (isShow) 
            Log.i("mvp_", "显示等待框");
         else 
            Log.i("mvp_", "隐藏等待框");
        
    

    public void showToast(String msg) 
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    

    protected abstract Object getLayout();

    protected abstract List<? extends BasePresenter> createPresenter();

    protected abstract void afterCreate();


实现类LoginActivity

主要是createPresenter() 方法,创建容器,然后把用到的loginPresenter 注入容器返回。如果有多个就注入多个P。

public class LoginActivity extends BaseMvpActivity implements LoginContract.IView 

    private LoginPresenter loginPresenter;

    @Override
    protected Object getLayout() 
        return R.layout.activity_main;
    


    @Override
    protected List<? extends BasePresenter> createPresenter() 
        ArrayList<BasePresenter> presenters = new ArrayList();
        loginPresenter = new LoginPresenter();
        presenters.add(loginPresenter);
        return presenters;
    

    @Override
    protected void afterCreate() 
        $(R.id.btn_login).setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                loginPresenter.onClickLogin("xxx", "xxx");
            
        );
    

    @Override
    public void goToMainActivity() 
        runOnUiThread(new Runnable() 
            @Override
            public void run() 
                //todo 登录成功跳转到主界面
                Log.i("mvp_", "登录成功跳转到主界面");
            
        );

    

    @Override
    public void showProgress(boolean isShow) 
        if (isShow) 
            Log.i("mvp_", "显示等待框");
         else 
            Log.i("mvp_", "隐藏等待框");
        
    

    @Override
    public void showToast(String str) 
        Toast.makeText(this, str, Toast.LENGTH_LONG).show();
    

这一小节就是讲解多个P的处理思想。非常简单,使用容器存储就Ok了。下一小节,讲解使用如何使用注解和反射形式创建P的实例对象。目的有两个(1)是减少基类(父类)和子类的直接依赖。基类不需要通过createPresenter方式 注入P的引用,(2)减少代码,去掉繁琐的创建操作。

以上是关于Android MVP-编程思想5(如何处理多个P层的问题?)的主要内容,如果未能解决你的问题,请参考以下文章

如何处理多个倾向于一个 apk 的 android 项目

Android MVP-编程思想6(依赖注入多个P层方式优化---注解,反射)

Android MVP-编程思想6(依赖注入多个P层方式优化---注解,反射)

从 RxJS 到 Flink:如何处理数据流?

从 RxJS 到 Flink:如何处理数据流?

Android/Parse-如何处理来自 ParseQuery 的多个回调