繁体   English   中英

在片段之间导航时保​​存状态

[英]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 Esbatirafid059的帮助下解决了这个问题(谢谢!)

由于我只有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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM