6

I found many way to avoid memory leaks in android fragment, but which is the best way?

1.Set the view to null when onDestroyView is called

public class LeakyFragment extends Fragment{

    private View mLeak; // retained

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mLeak = inflater.inflate(R.layout.whatever, container, false);
        return mLeak;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mLeak = null; // now cleaning up!
    }
}

2.Set all the child view = null and remove the view

    @Override
    public void onDestroyView(){
        super.onDestroyView();
        unbindDrawables(mLeak);
    }

    private void unbindDrawables(View view){
        if (view.getBackground() != null){
            view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup && !(view instanceof AdapterView)){
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++){
                unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
            ((ViewGroup) view).removeAllViews();
        }
    }
Samet ÖZTOPRAK
  • 3,112
  • 3
  • 32
  • 33
Chan HoNan
  • 61
  • 1
  • 3

1 Answers1

0

Setting a variable to null does not mean that it will get GC'd. It will only be GC'd if there are no other strong references to it anywhere.

Setting setRetainInstance(true) does not make your Fragment leak per se, it just preserves that instance of the Fragment across configuration changes. It may be considered a "conscious leak", since you are telling the framework you want to retain the Fragment object past the current Activity's lifecycle.

Now the Fragment will leak your Activity if it is not a UI-less Fragment. This happens because Fragments that have a UI will hold references to UI components(i.e. TextViews, EditTexts, etc), and these Views hold a reference of the Activity's Context. In order to avoid this, you need to set all of those references to null as you are doing.

Also, you probably also need to remove mLeak from its parent as well.

Emmanuel
  • 13,083
  • 4
  • 39
  • 53
  • 2
    Any sample to avoid memory leaks? I got out of memory on calling setContentView when i change a fragment in FragmentTabHost. – Chan HoNan Mar 03 '15 at 14:39
  • You might be trying to load an image that requires too much memory. Are you setting a drawable to an `ImageView`? – Emmanuel Mar 03 '15 at 14:41
  • DONT use setRetainInstance. – Pedro Paulo Amorim Mar 03 '15 at 14:41
  • You need say what you can do with this layout. Then we can help you. – Pedro Paulo Amorim Mar 03 '15 at 14:42
  • why shouldn't he use `setRetainInsance()` @PedroPauloAmorim? – Emmanuel Mar 03 '15 at 14:43
  • The fragment is not setting a drawable, but the xml layout has set some image in the ImageView. Those images about 600kb. – Chan HoNan Mar 03 '15 at 14:45
  • The amount of disk space an image takes is irrelevant when it comes to how much memory (RAM) the image takes. The amount of RAM an image takes is related to the resolution via the following equation `# of bytes in memory = imageWidth x imageHeight * 4` – Emmanuel Mar 03 '15 at 14:50
  • So, the solution is make the resolution of the image more lower? – Chan HoNan Mar 03 '15 at 14:54
  • Yeah, that is what I would recommend. – Emmanuel Mar 03 '15 at 15:20
  • @Emmanuel You need follow the Fragment lifecycle. setRentainInstance() is just a workaround. – Pedro Paulo Amorim Mar 03 '15 at 16:57
  • I do not understand why you think it is a workaround? a workaround for what? It is a convenience method for retaining a `Fragment` across configuration changes. I do not see a problem on using it if it is used for the correct reasons. – Emmanuel Mar 03 '15 at 17:01
  • @PedroPauloAmorim it helps if you use more than a statement but add some in detail explanations! – WarrenFaith Mar 03 '15 at 17:06
  • So, i should call setRetainInstance(true); in onCreate or other lifecycle? – Chan HoNan Mar 04 '15 at 15:22
  • If you use `setRetainInstance()` in a `Fragment` that has a UI you will leak the `Activity` if you do not set all the `Views` it references to `null` when the `Fragment` calls `onDestroyView`. I would only use `setRetainInstance()` with `Fragments` that do not have a UI. – Emmanuel Mar 04 '15 at 15:22
  • So I should make all of my textviews and imagebuttons null in the `onPause`? – Ruchir Baronia Jan 10 '16 at 00:43
  • i have same problem in recyclerview lagging please check my question @Emmanuel https://stackoverflow.com/questions/60880908/add-same-fragment-second-time-add-more-then-one-time-fragment-then-recyclervie – Kishan Viramgama Apr 03 '20 at 04:27