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();
}
}
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 yourFragment
leak per se, it just preserves that instance of theFragment
across configuration changes. It may be considered a "conscious leak", since you are telling the framework you want to retain theFragment
object past the currentActivity
's lifecycle.Now the
Fragment
will leak yourActivity
if it is not a UI-lessFragment
. This happens becauseFragments
that have a UI will hold references to UI components(i.e.TextViews
,EditTexts
, etc), and theseViews
hold a reference of theActivity
'sContext
. In order to avoid this, you need to set all of those references tonull
as you are doing.Also, you probably also need to remove
mLeak
from its parent as well.