Reputation: 61
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();
}
}
Upvotes: 6
Views: 9559
Reputation: 13233
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.
Upvotes: 0