3

我正在开发一个应用程序,我有一个带有 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();
}

我使用 switch case 来确定 Fragment 的类并将其发送到此方法。

我可能会想出一个 hacky-snappy 的方法来解决这个问题,但我想在没有太多 hacky-snappy 代码的情况下解决这个问题。

我希望有人知道如何解决这个问题。提前致谢。

编辑:

这是我的片段类:

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);
    }
}
4

2 回答 2

3

onSaveInstanceState没有被调用,因为没有理由,当您在片段之间导航时,旧片段不会被破坏,直到操作系统需要它们使用的空间(低内存)。

首先创建一个回栈来保存片段或者只是addtoBackStack在结束时调用fragmentTransaction然后将列表初始化和数据请求移动到 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;
}
于 2018-03-16T09:51:53.853 回答
2

编辑: 虽然这个解决方案工作正常,但这个解决方案使用了一些不好的做法,我建议改用接受的解决方案。

我在Keivan Esbatidenvercoder9的帮助下解决了这个问题(谢谢!)

因为我只有 4 个片段,所以我在 MainActivity 中保留了每个片段的实例,因此我还有一个变量来跟踪当前片段。每次打开片段时,我都会使用 FragmentManager 隐藏当前片段并调用.hide()事务。然后,如果 Fragment 是我在事务中调用的新 Fragment .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;
于 2018-03-16T11:14:15.230 回答