Fragment transaction animations lost when rotating screen - android

I show animation when user navigates away from fragment. For that I am using setCustomAndimations of support package.
"popEnter" and "popExit" work fine, but they are lost after activity gets rotated,
i.e. after rotation popping fragment happens without the animation.
Fragment creation in activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
if (savedInstanceState == null) { // activity started for the first time, no fragment attached yet
fragment = MyFragment.newInstance(params);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(0, 0, // enter animations, not important here
// when popping fragment -> these are lost on rotation
R.anim.slide_in_right, R.anim.slide_out_right);
ft.add(R.id.content, fragment, MY_TAG).addToBackStack(null).commit();
}
}
Is there way / workaround to keep animating "popping out" of fragment after rotation ?

I found a temporarily solution for this problem here (answer #3)
fix this by adding:
android:configChanges="orientation|screenSize"
to your FragmentActivity in the manifest.
There are of course problems, when you i.e. inflate different layouts in your onCreateView, depending on the screen size. So thats also not a final answer.
Edit: you can create your own backstack:
public final class MBackStack {
public static Stack<Fragment> fragStack = new Stack<>();
private MBackStack(){}
public static void addFragment(Fragment frag){
fragStack.push(frag);
}
public static Fragment getFragment(){
if (fragStack.isEmpty()) {
return null;
}
fragStack.pop();
Fragment fragment = fragStack.peek();
return fragment;
}
public static int getStackSize(){
return fragStack.size();
}
public static void clearStack(){
while (fragStack.size()!=0){
fragStack.pop();
}
}
}
Now instead of
ft.addToBackStack(null);
You can add:
YOURFRAGMENT yf = new YOURFRAGMENT();
MBackStack.addFragment(yf);
ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, dts);
ft.commit();
And in your main activity you can override your onbackpressed:
#Override
public void onBackPressed() {
if(MBackStack.getStackSize()>1){
ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.in_left, R.anim.out_right);
ft.replace(R.id.content_frame, MBackStack.getFragment());
ft.commit();
}else{
finish();
overridePendingTransition(R.anim.no_animation, R.anim.slide_bottom_out);
}
}
I have tried it, and it works fine.

Related

Finish a fragment with onBackPressed true?

I have a Fragment(TimerToAnswer) that I implemented onBackPressed() of a ActionBarActivity. Does Fragment can't return when isVisible true because there is a timer to answer a question. After the question is answer in Fragment(TimerToAnswer) I make redirect to other Fragment(ChooseQuestion) to choose other question to answer. In this stage when I pressed button back of device its return to Fragment(TimerToAnswer) again and I don't wanna that. For this problem, I'm trying finish() the Fragment(TimerToAnswer) but I can't do it.
I tried
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
or
getActivity().getSupportFragmentManager().popBackStack();
Here how I'm trying
ActionBarActivity
public class CustomDrawerLayout extends ActionBarActivity implements OnItemClickListener{
#Override
public void onBackPressed() {
TimerToAnswer tt = (TimerToAnswer)getSupportFragmentManager().findFragmentByTag("TimerToAnswer");
if(tt != null && tt.isVisible()){
return;
}else{
super.onBackPressed();
}
}
}
Fragment TimerToAnswer
public class TimerToAnswer extends Fragment implements AdapterView.OnItemClickListener {
if(answer){
FragmentTransaction ft;
Fragment frag;
frag = new ChooseQuestion();
Bundle params = new Bundle();
ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fl, frag);
ft.addToBackStack("back");
ft.commit();
removeFrag();
}
private void removeFrag(){
//getActivity().getSupportFragmentManager().popBackStack();
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
}
}
The reason it's returning to your TimerToAnswer fragment when the user presses back from ChooseQuestion is because of this line:
ft.addToBackStack("back");
What that does, as per the documentation:
Add this transaction to the back stack. This means that the transaction will be remembered after it is committed, and will reverse its operation when later popped off the stack.
To fix this, just remove that line.

Bring Fragment to Front (No fragment recreation)

I have three fragments F1 F2 F3 F4 all are accessible from sidebar.
all four can be called at any time and in any order,
Now I want if, F1 is already clicked(created) then never again create F1, but only bring back fragment F1 to front using fragment manager. Same for all other fragment
So far i tried this for every fragment in my container (FRAGMENT ACTIVITY)
if (fragmentManager.findFragmentByTag("apps")==null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
Fragment newFragment = new CategoriesFragment();
transaction.replace(R.id.content_frame, newFragment, "apps");
transaction.addToBackStack("apps");
transaction.commit();
} else{
}
If part ensures me NO fragment is recreated (If its created already) again, but what should i write in else part so that already created fragment can be brought to front in View Hierarchy
Please Help, i'm stuck at this for 2 days.
I would put this code in activity class, that must have FrameLayout with id R.id.fragment_container.
private Fragment1 F1;
private Fragment2 F2;
private Fragment3 F3;
private Fragment4 F4;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
F1 = new Fragment1();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, F1).commit();
F2 = new Fragment2();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, F2).commit();
F3 = new Fragment3();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, F3).commit();
F4 = new Fragment4();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, F4).commit();
//if needed show F1
getSupportFragmentManager().beginTransaction().show(F1).commit();
}
And add this for button click:
public void onBtnClick(View view){
if(mShowF1){
getSupportFragmentManager().beginTransaction().show(F1).commit();
getSupportFragmentManager().beginTransaction().hide(F2).commit();
getSupportFragmentManager().beginTransaction().hide(F3).commit();
getSupportFragmentManager().beginTransaction().hide(F4).commit();
}
//...
}
On button click(s) you can show, that fragment that you want and hide others.
NOTE (#developer1011):
For use after activity save state call commitAllowingStateLoss (). Use with care, because fragment is not restored with activity restoration.
NOTE:
MainActivity should implement OnFragmentInteractionListener for each Fragment.
public class MainActivity extends FragmentActivity implements Fragment1.OnFragmentInteractionListener, Fragment2.OnFragmentInteractionListener, Fragment3.OnFragmentInteractionListener, Fragment4.OnFragmentInteractionListener {//..
#Override
public void onFragmentInteraction(Uri uri) {
//
}
}
Get the fragment by tag and replace it in the container,
else{
Fragment existingFragment = (CategoriesFragment)fragmentManager.findFragmentByTag("apps");
transaction.replace(R.id.content_frame,existingFragment, "apps");
transaction.addToBackStack("apps");
transaction.commit();
}
UPDATE:
you can use hide and show fragment to avoid recreation.instead of using "transaction.replace()"
fragmentTransaction.hide(<oldFragment>);
fragmentTransaction.show(<newFragment>);
JAVA:
If you are just trying to add a Fragment without having to worry about recreating it then I think this method I have wrote to add Fragment will do you job.
public static void attachFragment ( int fragmentHolderLayoutId, Fragment fragment, Context context, String tag ) {
FragmentManager manager = ( (AppCompatActivity) context ).getSupportFragmentManager ();
manager.findFragmentByTag ( tag );
FragmentTransaction ft = manager.beginTransaction ();
if (manager.findFragmentByTag ( tag ) == null) { // No fragment in backStack with same tag..
ft.add ( fragmentHolderLayoutId, fragment, tag );
ft.addToBackStack ( tag );
ft.commit ();
}
else {
for (Fragment frag : manager.getFragments()){
ft.hide(frag)
}
ft.show ( manager.findFragmentByTag ( tag ) ).commit ();
}
}
Kotlin:
fun attachFragment(fragmentHolderLayoutId: Int, fragment: Fragment?, tag: String?) {
val manager: FragmentManager = supportFragmentManager
val ft: FragmentTransaction = manager.beginTransaction()
if (manager.findFragmentByTag(tag) == null) { // No fragment in backStack with same tag..
ft.add(fragmentHolderLayoutId, fragment!!, tag)
ft.addToBackStack(tag)
ft.commit()
} else {
//Hide other fragments
for (frag in manager.fragments){
ft.hide(frag)
}
//Shows the selected fragment.
ft.show(manager.findFragmentByTag(tag)!!).commit()
}
}
Use a simple ArrayList<Fragment> for your Fragments, and add them in order, so that you know get(0) will get F1, get(1) gets F2, etc.
Create the Fragments as singletons. In each fragment add a static field and method:
private static Fragment mMyInstance = null;
public static Fragment newInstance() {
if (mMyInstance == null) {
mMyInstance = new F1();
}
return mMyInstance;
}
Create the Fragments with the static method and add them to the ArrayList.
In each Fragment add the setRetainInstance(true); command to the onCreate() method.
Now when you add the Fragment with the FragmentManager, onCreate() will only be called the first time, but onCreateView() will be called every time. You want to inflate the view and wire the widgets each time, just en case your Activity got recreated because of a configuration change. But you can check something you add to see if it's the first time or not, and reset the widgets to their previous state if not. So, you will need member variables in your Fragments to keep track of their state. Override onStop() to save state, and reapply it in onCreateView() after wiring up the widgets.
Then when the sidebar button is pressed, you get the Fragment that corresponds to that button, remove the previous Fragment, and add the current one with the FragmentManager (or just use the replace() command instead of remov()/add()).
If you are using the Support Fragment, then this static method does the job.
/**
* Takes a Fragment TAG and tries to find the fragment in the manager if it exists and bring it to front.
* if not, will return false;
* #param manager
* #param tag
*/
public static boolean resurfaceFragment(FragmentManager manager, String tag ){
Fragment fragment = manager.findFragmentByTag(tag);
FragmentTransaction transaction = manager.beginTransaction();
if (fragment!=null){
for (int i = 0; i < manager.getFragments().size(); i++) {
Fragment f = manager.getFragments().get(i);
transaction.hide(f);
}
transaction.show(fragment).commit();
return true;
}
return false;
}

Fragment issue (Multiple instances)

I have this annoying problem which I don't know how to solve. The problem is very straightforward:
I have FragmentA which pushes FragmentB (a ListView) on a button click.
In FragmentB I can push FragmentA with a OnItemClick. So you see, the depth is infinite.
The problem is when I pushed FragmentB the second time, and then go back (2 times) to first instance of FragmentB I have the items from the first and second instance in the ListView. If I were about to make 10 instances, then I would have the items of all 10 instances in my first instance.
Can anyone explain the problem and please provide me a solution?
EDIT (code snippet):
FollowersFragment frag = new FollowersFragment();
Bundle bundle = new Bundle();
bundle.putString(Constants.USER_ID, userId);
frag.setArguments(bundle);
((MainActivity) getActivity()).pushFragment(frag);
public void pushFragment(TrigdFragment fragment) {
pushFragment(fragment, new AnimationObject());
}
public void pushFragment(TrigdFragment fragment, AnimationObject animate) {
switchContent(fragment, animate, false);
}
public void switchContent(TrigdFragment fragment, AnimationObject anim,
boolean clearBackStack) {
ActionBarHelper mActionBarHelper = ActionBarHelper.getInstance();
supportInvalidateOptionsMenu();
FragmentManager mgr = getSupportFragmentManager();
if (clearBackStack) {
mActionBarHelper.setDisplayHomeAsDrawerEnabled(true);
mgr.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
mActionBarHelper.setDisplayHomeAsUpEnabled(true);
}
fragment.setupActionBar(getResources());
FragmentTransaction ft = mgr.beginTransaction();
boolean doingAnimation = false;
if (Util.hasIcecreamSandwich()) {
doingAnimation = anim != null;
if (doingAnimation) {
ft.setCustomAnimations(anim.enterResource, anim.exitResource,
anim.popEnterResource, anim.popExitResource);
}
}
ft.replace(R.id.content_frame, fragment, "current");
if (!clearBackStack) {
ft.addToBackStack(null);
}
ft.commitAllowingStateLoss();
if (Util.hasIcecreamSandwich()) {
if (doingAnimation) {
// This can't be done immediately because the transaction may
// not
// yet be committed. Commits are are posted to the main
// thread's message loop.
mHandler.post(new Runnable() {
#SuppressLint("NewApi")
#Override
public void run() {
invalidateOptionsMenu();
}
});
}
}
}
Instead of creating new instance of the Fragments you can use replace function of FragmentTransaction
transaction.replace(R.id.fragment_container, newFragment);
Replacing one fragment with another in Android dynamically
http://notionink.wikidot.com/rajeshbabu
http://www.vogella.com/articles/AndroidFragments/article.html
This issue had nothing to do with multiple instances. It was a Listener which provided the problem, my mistake. Thanks for your effort though.

Show hide fragment in android

I am developing application which contains 2 fragments and i want to show hide according to my need. Following code has simple example of my problem.
This simple Fragmentactivity contains 1 button and one listfragment.
This simple example works flawless. but i am not satisfied with show hide fragment. If you remove layout.setVisibility(View.GONE); from the code then ft.hide(f); will not hide fragment. In fact we are not hiding fragment we are hiding container.
My Question is, IS this a way to show hide fragments? If not then please explain with tested example How to hide and show Fragments because lots of people are facing this problem.
public class MainActivity extends FragmentActivity implements OnClickListener {
Fragment1 f;
Button b;
LinearLayout layout;
Fragment myf;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b = (Button) findViewById(R.id.button1);
layout = (LinearLayout) findViewById(R.id.ll);
f = new Fragment1();
}
#Override
public void onClick(View v) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
if (f.isHidden()) {
ft.show(f);
layout.setVisibility(View.VISIBLE);
b.setText("Hide");
} else {
ft.hide(f);
b.setText("Show");
layout.setVisibility(View.GONE);
}
ft.commit();
// TODO Auto-generated method stub
}
Don't mess with the visibility flags of the container - FragmentTransaction.hide/show does that internally for you.
So the correct way to do this is:
FragmentManager fm = getFragmentManager();
fm.beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
.show(somefrag)
.commit();
OR if you are using android.support.v4.app.Fragment
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction()
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
.show(somefrag)
.commit();
In addittion, you can do in a Fragment (for example when getting server data failed):
getView().setVisibility(View.GONE);
Hi you do it by using this approach, all fragments will remain in the container once added initially and then we are simply revealing the desired fragment and hiding the others within the container.
// Within an activity
private FragmentA fragmentA;
private FragmentB fragmentB;
private FragmentC fragmentC;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
fragmentA = FragmentA.newInstance("foo");
fragmentB = FragmentB.newInstance("bar");
fragmentC = FragmentC.newInstance("baz");
}
}
// Replace the switch method
protected void displayFragmentA() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (fragmentA.isAdded()) { // if the fragment is already in container
ft.show(fragmentA);
} else { // fragment needs to be added to frame container
ft.add(R.id.flContainer, fragmentA, "A");
}
// Hide fragment B
if (fragmentB.isAdded()) { ft.hide(fragmentB); }
// Hide fragment C
if (fragmentC.isAdded()) { ft.hide(fragmentC); }
// Commit changes
ft.commit();
}
Please see https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments for more info. I hope I get to help anyone. Even if it this is an old question.
public void showHideFragment(final Fragment fragment){
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.animator.fade_in,
android.R.animator.fade_out);
if (fragment.isHidden()) {
ft.show(fragment);
Log.d("hidden","Show");
} else {
ft.hide(fragment);
Log.d("Shown","Hide");
}
ft.commit();
}
Try this:
MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.mapview);
mapFragment.getView().setVisibility(View.GONE);
I may be way way too late but it could help someone in the future.
This answer is a modification to mangu23 answer
I only added a for loop to avoid repetition and to easily add more fragments without boilerplate code.
We first need a list of the fragments that should be displayed
public class MainActivity extends AppCompatActivity{
//...
List<Fragment> fragmentList = new ArrayList<>();
}
Then we need to fill it with our fragments
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
HomeFragment homeFragment = new HomeFragment();
MessagesFragment messagesFragment = new MessagesFragment();
UserFragment userFragment = new UserFragment();
FavoriteFragment favoriteFragment = new FavoriteFragment();
MapFragment mapFragment = new MapFragment();
fragmentList.add(homeFragment);
fragmentList.add(messagesFragment);
fragmentList.add(userFragment);
fragmentList.add(favoriteFragment);
fragmentList.add(mapFragment);
}
And we need a way to know which fragment were selected from the list, so we need getFragmentIndex function
private int getFragmentIndex(Fragment fragment) {
int index = -1;
for (int i = 0; i < fragmentList.size(); i++) {
if (fragment.hashCode() == fragmentList.get(i).hashCode()){
return i;
}
}
return index;
}
And finally, the displayFragment method will like this:
private void displayFragment(Fragment fragment) {
int index = getFragmentIndex(fragment);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (fragment.isAdded()) { // if the fragment is already in container
transaction.show(fragment);
} else { // fragment needs to be added to frame container
transaction.add(R.id.placeholder, fragment);
}
// hiding the other fragments
for (int i = 0; i < fragmentList.size(); i++) {
if (fragmentList.get(i).isAdded() && i != index) {
transaction.hide(fragmentList.get(i));
}
}
transaction.commit();
}
In this way, we can call displayFragment(homeFragment) for example.
This will automatically show the HomeFragment and hide any other fragment in the list.
This solution allows you to append more fragments to the fragmentList without having to repeat the if statements in the old displayFragment version.
I hope someone will find this useful.
From my code, comparing to above solution, the simplest way is to define a layout which contains the fragment, then you could hide or unhide the fragment by controlling the layout attribute which is align with the general way of view. No additional code needed in this case and the additional deployment attributes of the fragment could be moved to the outer layout.
<LinearLayout style="#style/StHorizontalLinearView"
>
<fragment
android:layout_width="match_parent"
android:layout_height="390dp"
android:layout_alignParentTop="true"
/>
</LinearLayout>
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;
In onCreate, after setContentView, i hid two fragments and committed them to the fragment manager, but i didn't hide the first fragment that will serve as home.
fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();
#Override
public void onClick(View v) {
Fragment another = fragment1;
if(active==fragment1){
another = fragment2;
}
fm.beginTransaction().hide(active).show(another).commit();
active = another;
}
Ref : https://medium.com/#oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711
This worked for me
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if(tag.equalsIgnoreCase("dashboard")){
DashboardFragment dashboardFragment = (DashboardFragment)
fragmentManager.findFragmentByTag("dashboard");
if(dashboardFragment!=null) ft.show(dashboardFragment);
ShowcaseFragment showcaseFragment = (ShowcaseFragment)
fragmentManager.findFragmentByTag("showcase");
if(showcaseFragment!=null) ft.hide(showcaseFragment);
} else if(tag.equalsIgnoreCase("showcase")){
DashboardFragment dashboardFragment = (DashboardFragment)
fragmentManager.findFragmentByTag("dashboard");
if(dashboardFragment!=null) ft.hide(dashboardFragment);
ShowcaseFragment showcaseFragment = (ShowcaseFragment)
fragmentManager.findFragmentByTag("showcase");
if(showcaseFragment!=null) ft.show(showcaseFragment);
}
ft.commit();
the answers here are correct and i liked #Jyo the Whiff idea of a show and hide fragment implementation except the way he has it currently would hide the fragment on the first run so i added a slight change in that i added the isAdded check and show the fragment if its not already
public void showHideCardPreview(int id) {
FragmentManager fm = getSupportFragmentManager();
Bundle b = new Bundle();
b.putInt(Constants.CARD, id);
cardPreviewFragment.setArguments(b);
FragmentTransaction ft = fm.beginTransaction()
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
if (!cardPreviewFragment.isAdded()){
ft.add(R.id.full_screen_container, cardPreviewFragment);
ft.show(cardPreviewFragment);
} else {
if (cardPreviewFragment.isHidden()) {
Log.d(TAG,"++++++++++++++++++++ show");
ft.show(cardPreviewFragment);
} else {
Log.d(TAG,"++++++++++++++++++++ hide");
ft.hide(cardPreviewFragment);
}
}
ft.commit();
}

Memory issues - fragments

I recently refactored a application and replaced a ViewFlipper for a FrameLayout on which I swap between Fragments.
Each time user request one of the views:
public void showLibraryOf(long publisherId) {
library = new DownloadLibraryFragment(id, viewFactory());
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.container, library);
ft.commit();
library.setAdapterObserver(this);
}
public void showMyLibraryOf(long publisherId) {
myLibrary = new MyLibraryFragment(id, viewFactory());
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.container, myLibrary);
ft.commit();
}
public void showHelp() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.container, new HelpFragment());
ft.commit();
}
I create a new Fragment and replace the old one. Those being removed from screen get onDestroy called, but the memory consumed by the bitmaps I load on the screen does not get removed, so the application crashes after some swap between the fragments.
I also tried to remove references at onDestroy
#Override
public void onDestroyView() {
destroy();
super.onDestroyView();
adapter.clear();
adapter.clearObservers();
adapter.notifyDataSetChanged();
view.setAdapter(new ArrayAdapter<Journal>(getActivity(), 0));
adapter = null;
view = null;
}
But the memory keeps growing.
Anyone knows any solution? maybe reuse fragments? effectively destroy it? I'm listening.
I forget which stackoverflow question I originally pulled this code from, but one method that seems to work well is to override onAttachFragment of the FragmentActivity, and then store a WeakReference to each fragment passed in. Then, instead of using the replace method of a FragmentTransaction, you recycle all the fragments (as relevant for the case).
Here's an example of additional members and methods on a FragmentActivity that creates a default fragment in onCreate and responds to changes via onNewIntent:
private List<WeakReference<Fragment>> mFragments =
new ArrayList<WeakReference<Fragment>>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, MyFragment.newInstance("default"));
ft.commit();
}
#Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
String section = intent.getStringExtra("section");
recycleFragments();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, MyFragment.newInstance(section));
ft.commit();
}
#Override
public void onAttachFragment(Fragment fragment) {
mFragments.add(new WeakReference<Fragment>(fragment));
}
private void recycleFragments() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
for (WeakReference<Fragment> ref : mFragments) {
Fragment fragment = ref.get();
if (fragment != null) {
ft.remove(fragment);
}
}
ft.commit();
}
Now if you monitor the heap, you should notice it's not blowing up in size. This solution mostly comes into play when you have nested fragments containing bitmaps which for some reason don't seem to get recycled properly. I'd love a more elegant solution but this one works.

Categories

Resources