7

I read that retaining fragment with ui and references on views can cause memory leaks. Than I create test app with fragment where I store some references on views and set setRetaineInstance(true), but several screen rotation does not cause any leaks. MAT says that I have only one instance of parent activity. What I'm doing wrong? In which cases retaining fragment with ui can cause leaks?

RetainInstanceActivity.java

public class RetainInstanceActivity extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {        
    super.onCreate(savedInstanceState);

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(android.R.id.content, RetainFragment.newInstance())
                .commit();
    }
}}

RetainFragment.java

public class RetainFragment extends Fragment {

private View mLogin;
private View mPassword;
private View ImageView;

public static RetainFragment newInstance() {
    final RetainFragment fragment = new RetainFragment();

    return fragment;
}

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);        
}

@Override
public View onCreateView(final LayoutInflater inflater,
        final ViewGroup container, final Bundle savedInstanceState) {       
    final View view = inflater.inflate(R.layout.fragment_retain, container,
            false);

    mLogin = view.findViewById(R.id.login);
    mPassword = view.findViewById(R.id.password);
    ImageView = view.findViewById(R.id.img);

    return view;
}

}

Bracadabra
  • 3,609
  • 3
  • 26
  • 46

1 Answers1

7

Here you are retaining references to the old activity's mLogin, mPassword and ImageView views, but they are overwritten right after rotation, as onCreateView() will be called, so if your activity is the front activity and a configuration change happens you should be fine.

You might run into memory leaks when if your activity isnt the front activity, though, and in general you can't know how your fragment is handled.

For example the ViewPager has 2 different adapters, one (http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html) is retaining the Fragment instances (just calling onDestroyView()), while the other (FragmentStatePagerAdapter) is destroying the fragment instances.

So, your fragment would leak significant memory if used from a FragmentPagerAdapter.

I hope this serves as an example of potential problems. If you know what you are doing then there's no problem invoking setRetaineInstance(true) and not disposing the views.

Jacob Nordfalk
  • 3,533
  • 1
  • 21
  • 21
  • Thank you for your answer, but it does not seem to work this way. I have created a test app with two adapters and a pager with ten pages, but after paging through to the end, screen rotation and paging back I've got left 10 instances of fragment for FragmentPagerAdapter and 2 instances for FragmentStatePagerAdapter. – Bracadabra Sep 09 '13 at 18:27
  • You'd have to put a ZIP file somewhere, with a full projectfor me to look at, to see what is happening – Jacob Nordfalk Sep 16 '13 at 13:32
  • You can get project from this [repo](https://github.com/Drnkn/RetainInstanceTest). – Bracadabra Sep 18 '13 at 20:13
  • 4
    It works exactly as intended. FragmentPagerAdapter keeps all the 10 instances, and FragmentStatePagerAdapter only the visible instance and it's neighbours. You were asking about memory leaks, and here you have it: After a screen rotation FragmentPagerAdapter will call onCreateView on the visible instance and it's 2 neighbours, thus removing the old references to your buttons and imageview. The remaining 7 instances will keep their old references until the user swipes to view them. – Jacob Nordfalk Sep 20 '13 at 07:53