恢复ViewPager片段(MVP)的演示者

时间:2017-02-14 10:43:42

标签: android mvp android-mvp

我正在尝试重构现有的应用程序以使用MVP架构。其中一个活动有ViewPager个三个片段。每个片段都与演示者链接。确切地说 - 每个演示者在创建时都会被View使用,即Fragment。现在,我正在ViewPager的适配器中创建这些演示者 - 特别是在getItem(int position)方法中。

Fragment fragment = FirstFragment.newInstance();
FirstPresenter presenter = new FirstPresenter(repo, (FirstContract.View) fragment, projectId, userId);

我遇到的问题是如果进程被终止然后重新启动,ViewPager有自己的生命周期,因此不再调用getItem - 片段会自动重建,没有演示者。< / p>

这个问题是否有已知的解决方案?

4 个答案:

答案 0 :(得分:4)

由于这个问题仍然没有理想的答案,我认为分享我的临时解决方案可能会很好。

正如我在其中一条评论中提到的,这里的目标是从进程终止中恢复ViewPager,理想情况下将Presenter初始化与View分离。目前,我的解决方案是覆盖restoreState(Parcelable state, ClassLoader loader)中的FragmentStatePagerAdapter,检查状态Parcelable,类似于restoreState方法的实际实现,然后检查某个特定的每个片段我可以初始化一个演示者并为其指定一个视图。

@Override
public void restoreState(Parcelable state, ClassLoader loader) {
    if (state != null) {
        Bundle bundle = (Bundle)state;
        bundle.setClassLoader(loader);
        Iterable<String> keys = bundle.keySet();
        for (String key: keys) {
            if (key.startsWith("f")) {
                Fragment f = mFragmentManager.getFragment(bundle, key);
                if (f != null) {
                    if (f instanceof FirstFragment) {
                       new FirstPresenter(repo, (FirstContract.View) f, projectId, userId);
                    }
                } else {
                    Log.w(TAG, ".restoreState() - bad fragment at key " + key);
                }
            }
        }
    }

    super.restoreState(state, loader);
}

答案 1 :(得分:0)

如评论中所述 - 必须在Activity / Fragment生命周期方法中附加(和分离) Presenter 。不在外部课程中,因为只有查看可以在适当的时候设法附加 - 分离演示者在单独的类(或依赖注入框架)中初始化 Presenter 以将其与查看分离是一种很好的做法

答案 2 :(得分:0)

建议的答案对我不起作用,因为mFragmentManagerFragmentStatePagerAdapter的私人成员。不知道它对vkislicins有用吗。相反,我刚刚调用了父类来做restoreState然后使用&#39; instantiateItem&#39;抓取了片段。例如:

@Override
public void restoreState(Parcelable state, ClassLoader loader) {
    // this will load all the fragments again
    super.restoreState(state, loader);

    // since the fragments are now loaded, instantiate can be used because it just returns them
    MyFragmentClass tab1 = (MyFragmentClass) instantiateItem(null, 0);
    tab1Presenter.setView(tab1);
    tab1.setPresenter(tab1Presenter);

    // then just do the same for the other fragments
    ...
}

感觉有点hacky,但它确实有效。

答案 3 :(得分:0)

首先,我的解决方案包括FragmentManager.FragmentLifecycleCallbacks,这是一个

  

用于侦听在给定FragmentManager中发生的片段状态更改的回调接口

并以Android Architecture Blueprints中显示的方式坚持分离关注点,我会说。

  • Activity创建Presenter,传递View / Fragment,以便
  • Presenter知道其View并进一步设置自己的Presenter

Activity的{​​{1}}中,我通过调用

来注册onCreate听众
FragmentLifecycleCallbacks

private void registerFragmentsLifecycleListener() { // All registered callbacks will be automatically unregistered when // this FragmentManager is destroyed. getSupportFragmentManager.registerFragmentLifecycleCallbacks( new FragmentManager.FragmentLifecycleCallbacks() { // Called after the fragment has returned from its onActivityCreated @Override public void onFragmentActivityCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) { createPresenter(f); } }, false); // true to register callback for all child FragmentManagers } Fragment返回后,听众会收到通知,以确保只有{{>>新 onActivityCreated实例添加{} 1}}将创建一个新的Fragment。片段可以被连接/分离,它的视图可以创建/销毁几次,不需要做任何事情,仍然得到它的ViewPager

因为在娱乐的情况下(例如通过轮换)Presenter s'PresenterFragment之前被调用(onCreate听众注册了!) ,听众无法实现Activity,必须是FragmentLifecycleCallbacks

对于给定的新onFragmentCreated实例,我们可以确定需要哪个onFragmentActivityCreated

Fragment

Presenter与构建函数中的private void createPresenter(Fragment fragment) { if (fragment instanceof WhateverContract.View) { WhateverContract.Presenter whateverPresenter = new WhateverPresenter((WhateverContract.View) fragment); } else if (...){} } / Presenter相关联

View

然后可以在Fragment s private final WhateverContract.View mView; public WhateverPresenter(@NonNull WhateverContract.View view) { mView = checkNotNull(view, "view cannot be null!"); mView.setPresenter(this); }

中启动

如果出现问题或改进,请告诉我们:)