在活动中跨片段导航期间保存状态并刷新所有片段中的数据的最佳实践是什么?



所以我目前的实现如下。基本上我预加载所有片段,将它们设置为当前Activity的字段,然后添加或显示片段是否已添加。

mFeedTopicsFragment = FeedTopicsFragment.getInstance();
mUserDiscussionsFragment = UserDiscussionsFragment.getInstance(SessionPersistor.getSignedInUserId());
mUserConversationsFragment = MyConversationsFragment.getInstance(SessionPersistor.getSignedInUserId());
activityMainNavigation.setOnNavigationItemSelectedListener((MenuItem item) -> {
switch (item.getItemId()) {
case R.id.menu_item_go_to_feed_fragment:
if (getSupportFragmentManager().findFragmentByTag(FeedTopicsFragment.class.getSimpleName()) != null) {
getSupportFragmentManager()
.beginTransaction()
.show(mFeedTopicsFragment)
.hide(mUserDiscussionsFragment)
.hide(mUserConversationsFragment)
.commit();
} else {
getSupportFragmentManager()
.beginTransaction()
.add(R.id.activity_main_container_fragment, mFeedTopicsFragment, FeedTopicsFragment.class.getSimpleName())
.hide(mUserDiscussionsFragment)
.hide(mUserConversationsFragment)
.commit();
}
return true;
case R.id.menu_item_go_to_user_discussions_fragment:
if (getSupportFragmentManager().findFragmentByTag(UserDiscussionsFragment.class.getSimpleName()) != null) {
getSupportFragmentManager()
.beginTransaction()
.show(mUserDiscussionsFragment)
.hide(mFeedTopicsFragment)
.hide(mUserConversationsFragment)
.commit();
} else {
getSupportFragmentManager()
.beginTransaction()
.add(R.id.activity_main_container_fragment, mUserDiscussionsFragment, UserDiscussionsFragment.class.getSimpleName())
.hide(mFeedTopicsFragment)
.hide(mUserConversationsFragment)
.commit();
}
return true;
case R.id.menu_item_go_to_user_conversations_fragment:
if (getSupportFragmentManager().findFragmentByTag(MyConversationsFragment.class.getSimpleName()) != null) {
getSupportFragmentManager()
.beginTransaction()
.show(mUserConversationsFragment)
.hide(mFeedTopicsFragment)
.hide(mUserDiscussionsFragment)
.commit();
} else {
getSupportFragmentManager()
.beginTransaction()
.add(R.id.activity_main_container_fragment, mUserConversationsFragment, MyConversationsFragment.class.getSimpleName())
.hide(mFeedTopicsFragment)
.hide(mUserDiscussionsFragment)
.commit();
}
return true;

但是,我觉得这是一种糟糕的方法,因为我通过预加载片段来浪费内存。但是,我不想在每个FragmentTransaction调用replace因为每次都会调用onCreateView,并在每次我在片段之间导航时强制进行新的 API 调用。我不想这样,只要我留在这个Activity,比如说我从FeedTopicsFragment开始,向下滚动到RecyclerView的第10项,从FeedTopicsFragment导航到UserDiscussionsFragment,向下滚动到RecyclerView中的第三项,然后再回到FeedTopicsFragment,我还是会看到第10项, 回到UserDiscussionsFragment,我会看到第三项。

我正在考虑使用onSaveInstanceState来保存Bundle数据并将该Bundle加载到onActivityCreated中。但恐怕onSaveInstanceState可能不会被召唤,onActivityCreated也不会。那么,在不创建片段实例或将其另存为字段并在我离开活动后删除该状态的情况下保存状态的最佳解决方案是什么?

每个片段当前都有一个loadData方法,该方法在该方法中调用 API 并使用响应数据设置RecyclerViewTextView等字段。一旦我在活动中执行SwipeRefresh,它将对每个片段调用loadData

我也不确定如何做这个刷新部分,基本上我必须获取所有片段的实例,然后在每个片段上调用loadData。但一次只有一个片段在activity_main_container_fragment中。在这种情况下,我想保存每个片段的实例是有意义的,这样我就可以在这些本地实例上调用loadData

基本上,您可以在调用 API 之前检查 Arraylist 是否为空或空。

如果列表有数据,则在本地填写列表视图,

否则调用 API 以获取数据。

如果您从堆栈加载片段,那么它也将拥有其所有变量,如 arraylist。

首先,您应该考虑调用此方法来替换您的 Fragment,因为我看到您编写了太多代码。

/**
* replace or add fragment to the container
*
* @param fragment pass android.support.v4.app.Fragment
* @param bundle pass your extra bundle if any
* @param popBackStack if true it will clear back stack
* @param findInStack if true it will load old fragment if found
*/
public void replaceFragment(Fragment fragment, @Nullable Bundle bundle, boolean popBackStack, boolean findInStack) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
String tag = fragment.getClass().getName();
Fragment parentFragment;
if (findInStack && fm.findFragmentByTag(tag) != null) {
parentFragment = fm.findFragmentByTag(tag);
} else {
parentFragment = fragment;
}
// if user passes the @bundle in not null, then can be added to the fragment
if (bundle != null)
parentFragment.setArguments(bundle);
else parentFragment.setArguments(null);
// this is for the very first fragment not to be added into the back stack.
if (popBackStack) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
ft.addToBackStack(parentFragment.getClass().getName() + "");
}
ft.replace(R.id.contenedor_principal, parentFragment, tag);
ft.commit();
fm.executePendingTransactions();
}

像这样使用它

如果您的片段是主页或仪表板片段,则

Fragment f = new YourFragment();
replaceFragment(f, null, true, true); 

否则

Fragment f = new YourFragment();
replaceFragment(f, null, false, true); 

最新更新