[英]Save state when navigating between fragments
我正在开发一个应用程序,并且有一个带有NavigationDrawer的菜单,可以在片段之间导航。 在其中一个片段中,我调用了后端,然后将结果保存在列表中。 当我导航到另一个片段并返回时,结果消失了,但是我想暂时保存列表的内容。 我想使用onSaveInstanceState()
,但是该方法似乎从未被调用过。 我还查看了返回片段时数据是否仍在字段中,但事实并非如此。 我认为FragmentManager做错了,但是我不确定。
这是用于片段事务的方法:
private void openFragment(Class fragmentClass) {
Fragment fragment;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
return;
}
contentFrame.removeAllViews();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.contentFrame,fragment).commit();
}
我使用开关盒来确定Fragment的类,并将其发送给此方法。
我可能会想出一种解决问题的办法,但是我想在没有太多解决办法的代码的情况下解决此问题。
我希望有人对如何解决这个问题有所了解。 提前致谢。
编辑:
这是我的片段类:
public class LGSFragment extends Fragment {
@BindView(R.id.rvLGS)
RecyclerView rvLGS;
private List<LGS> lgsList;
private LGSAdapter adapter;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//I debugged here and all fields were null at this point
View view = inflater.inflate(R.layout.fragment_lgs,container,false);
ButterKnife.bind(this, view);
lgsList = new ArrayList<>();
LinearLayoutManager manager = new LinearLayoutManager(getContext());
rvLGS.setLayoutManager(manager);
adapter = new LGSAdapter(lgsList);
rvLGS.setAdapter(adapter);
getDatabaseLGSs();
return view;
}
/**
* Method to load in the LGSs from the database
*/
private void getDatabaseLGSs() {
String collection = getString(R.string.db_lgs);
FireStoreUtils.getAllDocumentsConverted(collection, LGS.class, new OperationCompletedListener() {
@Override
public void onOperationComplete(Result result, Object... data) {
if (result == Result.SUCCESS) {
lgsList.clear();
List<LGS> newLGSs = (List<LGS>) data[0];
List<String> ids = (List<String>) data[1];
int i = 0;
for (LGS lgs : newLGSs) {
lgs.setId(ids.get(i));
lgsList.add(lgs);
i++;
}
adapter.notifyDataSetChanged();
}
}
});
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
}
}
之所以不会调用onSaveInstanceState
是因为没有理由去 ,当您在片段之间导航时,直到操作系统需要它们使用的空间(低内存),较旧的片段才会被销毁。
首先创建一个后向堆栈以保留片段,或者只是在fragmentTransaction
的末尾调用addtoBackStack
,然后将列表初始化和数据请求移至onCreate,以便仅在创建片段时调用:
lgsList = new ArrayList<>();
getDatabaseLGSs();
之后,每次您返回片段时,都会使用可用数据重新创建视图。
更新:您可以将片段添加到backstack
,然后使用相应的tag
进行检索,而不是自己保留引用。 让我们fragmentManager自行管理缓存。 第二次访问片段时,不会重新创建它:
@Override
public void onNavigationDrawerItemSelected(@NonNull MenuItem item) {
if (item.isChecked())
return;
item.setChecked(true);
setTitle(item.getTitle());
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment currentlyShown = fragmentManager.findFragmentByTag(currentlyShownTag);
Fragment dest;
switch (item.getItemId()){
case R.id.nav_lgs:
dest = fragmentManager.findFragmentByTag(LGSFragment.class.getName());
if (dest == null) {
Log.d("TRANSACTION", "instanciating new fragment");
dest = new LGSFragment();
currentlyShownTag = LGSFragment.class.getName();
transaction.add(R.id.contentFrame, dest, LGSFragment.class.getName());
}
break;
...
}
if(currentlyShown != null)
transaction.hide(currentlyShown);
transaction.show(dest);
transaction.commit();
drawerLayout.closeDrawers();
return true;
}
编辑:尽管此解决方案效果很好,但此解决方案使用了一些不良做法,我建议改用可接受的解决方案。
我已经在Keivan Esbati和rafid059的帮助下解决了这个问题(谢谢!)
由于我只有4个片段,因此我在MainActivity中保留了每个片段的一个实例,因此我还有一个变量来跟踪当前片段。 每次打开片段时,我都会使用FragmentManager并在事务中调用.hide()
来隐藏当前片段。 然后,如果该片段是新片段,则在事务中调用.add()
,否则在事务中调用.show
。
onNavigationItemSelected()
方法的代码(当用户在菜单中选择一个项目时触发):
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
if (!item.isChecked()) {
item.setChecked(true);
setTitle(item.getTitle());
switch (item.getItemId()) {
case R.id.nav_lgs: {
if (lgsFragment == null) {
lgsFragment = new LGSFragment();
openFragment(lgsFragment, FragmentTag.LGS.toString());
} else {
openFragment(lgsFragment, "");
}
currentFragmentTag = FragmentTag.LGS;
break;
}
case R.id.nav_users: {
if (userFragment == null) {
userFragment = new UserFragment();
openFragment(userFragment, FragmentTag.USERS.toString());
} else {
openFragment(userFragment, "");
}
currentFragmentTag = FragmentTag.USERS;
break;
}
case R.id.nav_profile: {
if (profileFragment == null) {
profileFragment = new ProfileFragment();
openFragment(profileFragment, FragmentTag.PROFILE.toString());
} else {
openFragment(profileFragment, "");
}
currentFragmentTag = FragmentTag.PROFILE;
break;
}
case R.id.nav_my_lgs: {
if (myLGSFragment == null) {
myLGSFragment = new MyLGSFragment();
openFragment(myLGSFragment, FragmentTag.MY_LGS.toString());
} else {
openFragment(myLGSFragment, "");
}
currentFragmentTag = FragmentTag.MY_LGS;
break;
}
default: {
if (lgsFragment == null) {
lgsFragment = new LGSFragment();
openFragment(lgsFragment, FragmentTag.LGS.toString());
} else {
openFragment(lgsFragment, "");
}
currentFragmentTag = FragmentTag.LGS;
break;
}
}
}
drawerLayout.closeDrawers();
return true;
}
上面使用的openFragment()
方法:
private void openFragment(Fragment fragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
if (currentFragmentTag != FragmentTag.NO_FRAGMENT) {
fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag(currentFragmentTag.toString())).commit();
}
if (!tag.equals("")) {
fragmentManager.beginTransaction().add(R.id.contentFrame,fragment,tag).commit();
} else {
fragmentManager.beginTransaction().show(fragment).commit();
}
}
在onCreate()
:
currentFragmentTag = FragmentTag.NO_FRAGMENT;
if (lgsFragment == null) {
lgsFragment = new LGSFragment();
openFragment(lgsFragment, FragmentTag.LGS.toString());
} else {
openFragment(lgsFragment, "");
}
currentFragmentTag = FragmentTag.LGS;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.