Nicola Fanelli
Nicola Fanelli

Reputation: 552

findFragmentByTag() returns null on existing fragmentTag

I have an Activity with a FragmentContainer that will show only one of two Fragments.
By clicking on a Button of the first Fragment (CreateTasksListFragment), it is possible to show the other one (CreateTaskFragment).
When the user clicks on that button, CreateTasksListFragment gets hidden and a new instance of CreateTaskFragment is showed. Then, CreateTasksListFragment will be shown (by clicking on a button of CreateTaskFragment), and CreateTaskFragment has to be deleted.
The problem is that when I try to get the last instance of CreateTasksListFragment from the FragmentManager to show it again, even if I got its tag correctly by calling getBackStackEntryAt(), findFragmentByTag() returns null.
I don't think there're pending transactions, so probably I'm making another kind of mistake.
If you know better ways to achieve this goal, even without using this approach, please share them.

Here's the code interested by the issue:

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

Log

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

The tag is the same I've used when I put the first transaction on the backstack.

Upvotes: 1

Views: 173

Answers (1)

ianhanniballake
ianhanniballake

Reputation: 199825

The name you get back from fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 2).getName() is the name, you passed to addToBackStack(String name). That's an entirely separate concept from the tag associated with a fragment.

If you want to set a tag associated with a fragment, you need to set one as part of your replace() call using the version that takes a tag:

getSupportFragmentManager().beginTransaction()
        .replace(R.id.create_tasks_fragment_container, fragment, fragmentTag)
        .addToBackStack(fragmentTag)
        .commit();

Note: you should never mix a fragments transactions that use addToBackStack() with transactions that do not use addToBackStack() as this will break the behavior of popBackStack() and the system back button (which assumes you have not changed any of the fragments since the last addToBackStack() transaction).

Upvotes: 3

Related Questions