Double check the implementation of the template holder fragment +

I reworked some code due to a memory leak. The code is part of the application help section in which we use FragmentActivity and FragmentPageAdapter so that the user can scroll through various help screens. Each snippet, the SectionFragment class below, includes an image, some header text, and body text.

A memory leak occurred because a new view was inflated every time the onCreateView was called in the Fragment.

public class SectionFragment extends Fragment { private ImageView imgvw; private TextView headerTxvw; private TextView bodyTxvw; public int[][] content; protected int pageIdx; public SectionFragment(int idx, int[][] content ){ super(); pageIdx = idx; this.content = content; } protected int getPageIdx() { return pageIdx; } protected Drawable getImageDrawable() { return getResources().getDrawable( content[pageIdx][0] ); } protected String getHeaderText() { return getResources().getString( content[pageIdx][1] ); } protected String getSubeaderText() { return getResources().getString( content[pageIdx][2] ); } protected void loadView( View vw ) { imgvw = (ImageView)vw.findViewById( R.id.top_img ); headerTxvw = (TextView)vw.findViewById( R.id.header_txt ); bodyTxvw = (TextView)vw.findViewById( R.id.body_txt ); imgvw.setImageDrawable( getImageDrawable() ); headerTxvw.setText( getHeaderText() ); bodyTxvw.setText( getSubeaderText() ); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View vw = inflater.inflate( R.layout.help_fragment, null ); loadView( vw ); return vw; } } 

I am still new to Fragments and was not part of the initial coding effort, so I'm not sure my solution is correct, but it resembles a view holder template that I implemented many times in the Activity List. I would really appreciate any feedback on the next implementation, so I would be better off if that were correct.

 public class SectionFragment extends Fragment { static private class ViewHolder { ImageView imgvw; TextView headerTxvw; TextView bodyTxvw; } public int[][] _content; protected int _pageIdx; public SectionFragment( int idx, int[][] content ){ super(); _pageIdx = idx; _content = content; } protected int getPageIdx() { return _pageIdx; } protected Drawable getImageDrawable() { return getResources().getDrawable( _content[_pageIdx][0] ); } protected String getHeaderText() { return getResources().getString( _content[_pageIdx][1] ); } protected String getSubeaderText() { return getResources().getString( _content[_pageIdx][2] ); } protected void loadView( View vw ) { _holder.imgvw.setImageDrawable( getImageDrawable() ); _holder.headerTxvw.setText( getHeaderText() ); _holder.bodyTxvw.setText( getSubeaderText() ); } private View _vw; private ViewHolder _holder; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if ( _vw == null ) { _vw = inflater.inflate( R.layout.help_fragment, null ); _holder = new ViewHolder(); _holder.imgvw = (ImageView)_vw.findViewById( R.id.top_img ); _holder.headerTxvw = (TextView)_vw.findViewById( R.id.header_txt ); _holder.bodyTxvw = (TextView)_vw.findViewById( R.id.body_txt ); _vw.setTag( _holder ); } else { ViewParent oldparent = (ViewParent)_vw.getParent(); if ( oldparent != container ) { ((ViewGroup)oldparent).removeView( _vw ); } _holder = (ViewHolder)_vw.getTag(); } loadView( _vw ); return _vw; } } 

I did not include other classes related to this code, in particular FragmentActivity and FragmentPagerAdapter, because they seem to be implemented correctly, but if necessary, I can also include them.

+6
source share
1 answer

Memory leaks in Android applications in general

Are you sure this is a memory leak, not just a delay in garbage collection? Have you, for example, launched the eclipse memory analyzer plugin in an application? It can often show where the leak occurs.

In the mode of viewing a fragment and its disposal (or its absence)

My first assumption of memory leak / enlargement in the pager fragments has a dynamic adapter. The fragmentpageradapter is pretty dumb and will not handle changes well .

As far as I can see from the source, it will never destroy fragments, even if, for example, you change the count from 5 to 4 (the fifth fragment will remain in the fragment manager). This is due to the fact that it is removed, and not destroyed. fragstatepageradapter , however, will destroy views if they are outside the page margin.

And all this does not actually lead to memory leaks in the end, because these fragments will be cleared when the fragmenter is cleared of fragments later. However, it can slightly increase memory usage (potentially leading to outofmemoryerror).

A new view is created each time a fragment is created (and more often than when keepinstance is set to true), but if you do not use the FragmentStatePagerAdapter, which should appear only once per fragment, since a normal pager adapter disconnects and attaches the same fragments from the manager fragments. And in any case, the view will be deleted after the action is destroyed, if you do not save links to it.

It seems that you keep references to representations in your class, which I usually try to avoid. I prefer to use getView (). FindViewById () when I need them, but in this case, I think that member references should be found and removed by gc. It all depends on whether you have comforted these links elsewhere.

In the viewport in the fragment player

You should not try to do something like a viewer in a fragment. In this example, this probably won't hurt, but I don’t see you getting anything from him. Just inflate the view in oncreateview and set the values ​​and do with it.

There is no reprocessing of views in the list, so the ViewHolder template does not make sense and there are only risks associated with a memory leak or delayed garbage collection due to freezing links.

Views are not intended to be reused, even if they might be during any of the original tricks you used. This should be done only as a final exit. If nothing happens in the stream, this can lead to terrible leaks.

Please correct me if anyone can see reasonable use.

ViewHolder Side Note

I would really refrain from using the viewer if I really didn't need him even on the list. I saw that these tags lead to really nasty memory leaks, like some cursor adapters, for example, and I would look to make my line layouts easier before trying to save links. Findviewbyid will not be so expensive in a good layout.

+11
source

Source: https://habr.com/ru/post/911984/


All Articles