The best way to avoid memory leaks in android frag

2019-05-07 20:15发布

问题:

I found many way to avoid memory leaks in android fragment, 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();
        }
    }

回答1:

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.