findFragmentByTag() returns 现有 fragmentTag 为空

findFragmentByTag() returns null on existing fragmentTag

我有一个 Activity 和一个 FragmentContainer,它只会显示两个 Fragment 之一。
通过单击第一个 Fragment (CreateTasksListFragment) 的 Button,可以显示另一个 (CreateTaskFragment)。
当用户单击该按钮时,CreateTasksListFragment 被隐藏并显示 CreateTaskFragment 的新实例。然后,将显示 CreateTasksListFragment(通过单击 CreateTaskFragment 的按钮),并且必须删除 CreateTaskFragment
问题是,当我尝试从 FragmentManager 中获取 CreateTasksListFragment 的最后一个实例以再次显示它时,即使我通过调用 getBackStackEntryAt()findFragmentByTag() 正确地获得了它的标签returns 空.
我不认为有待处理的交易,所以我可能犯了另一种错误。
如果您知道实现此目标的更好方法,即使不使用这种方法,也请分享它们。

这里是问题感兴趣的代码:

CreateTasksActivity.java

@Override
protected void onStart() {
    super.onStart();
    Bundle bundle = new Bundle();
    ...

    CreateTasksListFragment fragment = new CreateTasksListFragment();
    fragment.setArguments(bundle);

    setCurrentFragment(fragment, CreateTasksListFragment.TAG);
}

/**
 * Sets new fragment
 * @param fragment
 */
public void setCurrentFragment(Fragment fragment, String fragmentTag){
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.create_tasks_fragment_container, fragment)
            .addToBackStack(fragmentTag)
            .commit();
}

CreateTasksListFragment.java

mNewTaskFabButton.setOnClickListener(v -> {
    Task task = new Task(mTasks.size() + 1);
    mTasks.add(task);

    Bundle bundle = new Bundle();
    bundle.putParcelable(CreateTaskFragment.TASK_EXTRA, task);
    CreateTaskFragment fragment = new CreateTaskFragment();
    fragment.setArguments(bundle);

    // Replacing fragment with the fragment to create a single task
    getParentFragmentManager()
            .beginTransaction()
            .hide(CreateTasksListFragment.this)
            .add(R.id.create_tasks_fragment_container, fragment)
            .addToBackStack(null)
            .commit();
});

CreateTaskFragment.java

mCreateTaskButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ...

        FragmentManager fm = getParentFragmentManager();
        Fragment fragment;

        String fragmentTag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 2).getName(); // -2 since it starts counting from 0 and we need the second-last transaction
        Log.d("log1", fragmentTag);
        fragment = fm.findFragmentByTag(fragmentTag);
        Log.d("log2", String.valueOf(fragment == null));
        fm.beginTransaction()
                .remove(CreateTaskFragment.this)
                .show(fragment)
                .commit();
    }
});

日志

2021-05-13 21:19:44.952 20865-20865/* D/log1: CreateTasksListFragmentTag
2021-05-13 21:19:44.952 20865-20865/* D/log2: true

标签与我将第一笔交易放在后台堆栈时使用的标签相同。

您从 fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 2).getName() 返回的 namename,您传递给 addToBackStack(String name)。这是与片段关联的标签完全不同的概念。

如果要设置与片段关联的标签,则需要使用 takes a tag:

的版本将一个标签设置为 replace() 调用的一部分
getSupportFragmentManager().beginTransaction()
        .replace(R.id.create_tasks_fragment_container, fragment, fragmentTag)
        .addToBackStack(fragmentTag)
        .commit();

注意:您应该 永远不要 将使用 addToBackStack() 的片段交易与不使用 addToBackStack() 的交易混合,因为这会破坏 [= =18=] 和系统后退按钮(假定自上次 addToBackStack() 交易以来您没有更改任何片段)。