我正在尝试重构现有的应用程序以使用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>
这个问题是否有已知的解决方案?
答案 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)
建议的答案对我不起作用,因为mFragmentManager
是FragmentStatePagerAdapter
的私人成员。不知道它对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'Presenter
在Fragment
之前被调用(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);
}
。
如果出现问题或改进,请告诉我们:)