Fragment系列(一)------View与Presenter

来源:互联网 发布:php 私有属性 编辑:程序博客网 时间:2024/06/10 12:59

(注:由于手机号验证问题,n6323438的博文转移至此)
今天要介绍的是github上一个Android开源框架: android-starter-kit (Rx部分)

链接: https://github.com/qijitech/android-starter-kit

fragment系列:
(一)View与Presenter
(二)NetworkFragment
(三)RecyclerFragment之UI部分

(建议先看一下里面的demo)

本文将介绍底层的2个fragment, 这个fragment连接了presenter, 实现了MVP

PresenterFactory

介绍这个fragment之前, 先要讲讲PresenterFactory.
PresenterFactory是一个接口, 里面很简单, 就一个 P createPresenter()方法.
ReflectionPresenterFactory是其中一个实例,
内部变量: private Class<P> presenterClass;
这个变量在构造的时候被传入, 当需要presenter的时候, 就可以通过反射构造一个presenter
现在来看构造方法
有2个构造方法, 第一个就是直接传入参数构造, 第二个是一个静态方法, 看:

public static <P extends Presenter> ReflectionPresenterFactory<P> fromViewClass(Class<?> viewClass) {        RequiresPresenter annotation = viewClass.getAnnotation(RequiresPresenter.class);        Class<P> presenterClass = annotation == null ? null : (Class<P>)annotation.value();        return presenterClass == null ? null : new ReflectionPresenterFactory<>(presenterClass);    }

可以看出, 传入一个viewClass, 然后通过注解读取需要哪一个presenter, 就得到ReflectionPresenterFactory了.

NucleusSupportFragment

好, 现在可以看fragment了
首先出场的是NucleusSupportFragment
NucleusSupportFragment<P extends Presenter> extends Fragment
内部变量:

private PresenterLifecycleDelegate&lt;P> presenterDelegate =        new PresenterLifecycleDelegate<>(ReflectionPresenterFactory.&lt;P>fromViewClass(getClass()));

这个类在构造的时候就会构造ReflectionPresenterFactory, 用的是静态方法.
而且, fragment并不是直接管理这个PresenterFactory, 而是把它交给PresenterLifecycleDelegate管理.


先来看看,我们最关心的getPresenter()方法:

public P getPresenter() {        if (presenterFactory != null) {            if (presenter == null && bundle != null)                presenter = PresenterStorage.INSTANCE.getPresenter(bundle.getString(PRESENTER_ID_KEY));            if (presenter == null) {                presenter = presenterFactory.createPresenter();                PresenterStorage.INSTANCE.add(presenter);                presenter.create(bundle == null ? null : bundle.getBundle(PRESENTER_KEY));            }            bundle = null;        }        return presenter;    }

这个方法就是如果presenter为null,则通过factory构造,并调用presenter的create方法.
就是说第一次调用getPresenter的时候, presenter才会被创建.
这里有一个细节, 当presenter通过factory构造出来后, 有个叫PresenterStorage的类也会持有这个presenter的引用, 并在presenter那里注册一个监听, 当presenter要被销毁的时候, PresenterStorage就会知道并也不再持有引用.

现在来看fragment的其他方法

onCreate:

主要是如果bundle不为null, 则通过bundle恢复presenter

onResume:

就是调用了presenterDelegate的onResume方法, 参数为fragment自己, 现在进入到presenterDelegate来看:
在delegate的onResume方法里, 首先调用getPresenter方法, getPresenter完成后,把传入的参数(也就是view)交给presenter保存.
这里可以看出, presenter最晚会在界面第一次出现的时候被创建

onPause:

调用delegate的onDropView方法, 就是让presenter不再持有view的引用, view=null

onDestroy:

也是调用delegate的onDestroy方法
这个方法先看是不是activity要重启(例如横竖屏转换), 如果activity不是重启而是真的要destroy了, presenter就会调用上面提到的那个监听, 然后delegate放弃对presenter的引用(presenter = null).
总的来看, NucleusSupportFragment连接了view和presenter, 当activity处于不可交互状态时, presenter不再持有view. 而且解决了activity的Configurations变化时,presenter反复构造的问题.

StarterFragment

接下来, 看另一个fragment
StarterFragment<P extends Presenter> extends NucleusSupportFragment<P>
先看onCreate:

@Override public void onCreate(Bundle bundle) {    final PresenterFactory<P> superFactory = super.getPresenterFactory();    setPresenterFactory(superFactory == null ? null : new PresenterFactory<P>() {      @Override public P createPresenter() {        return superFactory.createPresenter();      }    });    super.onCreate(bundle);    Icepick.restoreInstanceState(this, bundle);    starterCommon = StarterCommon.create(getActivity());  }

这里有点特别, 第一步并不是执行super方法,
而是获取presenterFactory, 然后新建一个PresenterFactory, 然后createPresenter就是调用刚才获取的presenterFactory的createPresenter. 这里, 我也不知道为什么要这样写, 可能是想加入一些处理吧.
注意, 这里就有个坑了.
这个坑就在setPresenterFactory这里, 这个方法是前面的NucleusSupportFragment的.
setPresenterFactory就是调用delegate的setPresenterFactory方法

public void setPresenterFactory(@Nullable PresenterFactory<P> presenterFactory) {        if (presenter != null)            throw new IllegalArgumentException("setPresenterFactory() should be called before onResume()");        this.presenterFactory = presenterFactory;    }

这里的含义就是说, 如果presenter已经通过factory构造出来了,然后你又要改变presenterFactory, 这会引起混乱.
这里告诉我们, 如果你继承了StarterFragment, 那么必须在starterFragment的onCreate调用完之后, 再getPresenter.
那fragment的onCreate什么时候调用呢?
根据我做的测试, 如果在activity的onCreate里new一个fragment并提交FragmentTransaction, 在activity的onStart里才会执行fragment的onCreate.
所以, 在activity的onCreate里, 千万不要new了一个fragment后马上调用getPresenter.

再看看其他方法

onCreateView

把获取layout_id抽取出一个方法 getFragmentLayout(),没什么特别.

onViewCreated

调用ButterKnife.bind,所以不需要自己写啦.

还提供了hide / showSoftInputMethod方法,通过starterCommon来完成.

到此, 这2个fragment看完了, 下一篇就要看StarterNetworkFragment