Reputation: 552
I have an Activity
with a FragmentContainer
that will show only one of two Fragment
s.
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
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