I have a Fragment stack, which fragments are added to (not replaced). The problem is, because of memory issues, I don't want to have more than a specific amount of fragments in the stack. Suppose I have added fragments A, B, C, D to the stack. Now that I want to add the Fragment E, I want the A to be removed, using this piece of code:
fragmentManager.beginTransaction().remove(fragmentA).commit()
I get fragmentA using findFragmentByTag() and I am sure fragmentA exists and is in the stack. But this has no effect, and doesn't remove fragmentA.
What's wrong you think?
Is it possible to remove a fragment from bottom of the stack?
Related
I have two fragments A and B.
A is a form which contains EditTexts and one value need to be selected from fragment B.
When using navigation component after selecting item from B and when conditionally navigating to A , EditTexts values are gone. The fragment is recreated. How to prevent this?
My intention is to get value from B to A without recreating A
Without seeing your code its difficult to give you a straight answer, but here are some general ideas
1) Add fragment A to the backstack this will persist it when you return from Fragment B
2) Find fragment A by its tag and if it exists do not create a new Fragment A when returning to it
My situation: I have two ListFragments (call them A and B) managed by one Activity which keeps persistent references to both of these Fragments. When I click a button in Fragment A, I replace that with Fragment B. The problem starts when I do the following flow.
A -> B -> (scroll) -> (back button) -> B
In that case, when I go back to Fragment B the second time, the previous scroll position is maintained, which I don't want. Instead, I would like for Fragment B to start with its ListView at the top of its content.
Things I have tried which do nothing:
Calling setSelection(0) in onActivityCreated
Calling setSelectionAfterHeaderViews() in onActivityCreated
Calling smoothScrollToPosition(0) in onActivityCreated
Interestingly, all of these work if I post them on a Runnable. However, when I do that there is a weird flickering the second time I open Fragment B.
So, how do I get Fragment B to automatically scroll to the top each time it is attached to its parent Activity? I feel like there must be something blindingly obvious that I'm missing, but I'm really stumped right now.
You're calling the right methods, but you're calling them in the wrong place.
I assume you have code that switches between the fragments and you call it when an item is clicked in A. So whenever you do the switch set the scroll to the top, something along these lines:
protected void switchList() {
ListFragment a = (ListFragment) getFragmentManager().findFragmentByTag("a");
ListFragment b = (ListFragment) getFragmentManager().findFragmentByTag("b");
b.getListView().setSelectionAfterHeaderView();
getFragmentManager().beginTransaction().hide(a).show(b).addToBackStack(null).commit();
}
And one important note: never keep persistent references to fragments in your activities. Whenever you need a fragment get it from the FragmentManager. This is crucial since on configuration change (like a device rotation, or when your app is suspended and restored) the fragments are recreated, and the reference you kept leads to a 'dead' fragment. Not only is it a major leak, it will also prevent your code from functioning. any change you make to the saved fragment is not reflected on the screen because the screen holds the newly created fragment.
I've implemented navigation in my Android app as one Activity and many Fragments.
When I open new child Fragment, I call this:
FragmentTransaction tx = getSupportFragmentManager().beginTransaction() .addToBackStack(null).replace(R.id.fragment_container, f)
.setBreadCrumbTitle(f.getClass().getSimpleName());
tx.commit()
This works quite well, as old fragment isn't destroyed, so when I go back in the back stack, the old fragment retains the scroll position and everything entered on it.
The problem is, in one Fragment I actually need to pause something when I add another fragment above it. I've thought that onPause() will be called, but it doesn't - I suppose that all other fragments live beneath the ones on top of them.
On the side note, I also think that my app gradually slows down as the user navigates deeper. Shouldn't I be replacing the fragment in the transaction instead, so only one is on the top?
I have looked around and found variations of this question, but all of the answers seem to be ugly hacks. Is there no easy and proper way to achieve this?
Say for instance I have Activity A, which has a FrameLayout that can hold one fragment at a time. Lets say that when the Activity is first started it loads Fragment A into the FrameLayout, which consists of a ListView. When an item is selected in Fragment A it starts up Fragment B. The way I am currently doing this is by simply hiding Fragment A and then adding Fragment B since this preserves Fragment A's state. I am of course also adding this fragment transaction to the backstack.
So now Fragment A exists on the backstack. Say now I go back to my Android home screen and go to another app. While I am doing this, the Android system decides to destroy my application because the system needs more memory. When I navigate back to my application, how am I supposed to properly restore the state of Fragment B, and Fragment A which is currently on the backstack.
I cannot use setRetainInstance() since it does not work for Fragments placed on the backstack.
Essentially what I am trying to do is restore the backstack to exactly how it was before my application was forcefully closed. So Fragment A should be on the backstack (but not showing), and Fragment B should be currently showing. If I hit the back button, it should properly pop Fragment A off the backstack.
Some notes
Since the application was forcefully closed, it's savedInstanceState != null. Same thing holds for the fragments.
I would like my fragments backstack to have a single instance of every fragment added to it. In other words, when I recall a fragment already instantiated (and added to the backstack) without popping it from the backstack (i.e. with a FragmentTransaction.replace by passing its tag name) I would like it to have it ONLY on the top of the FragmentManager's backstack. I can use FragmentTransaction.addToBackstack, but this cannot delete previous fragment references and I don't want to pop the backstack to erase the previous reference, otherwise I lose part of the history I still would like to retain.