android – 仔细检查片段视图持有者模式是否正确实现

前端之家收集整理的这篇文章主要介绍了android – 仔细检查片段视图持有者模式是否正确实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
由于内存泄漏,我一直在重新编写代码.代码是应用程序帮助部分的一部分,我们使用FragmentActivity和FragmentPageAdapter来允许用户滑动不同的帮助屏幕.下面的每个片段SectionFragment类包括一个图像,一些标题文本和正文.

内存泄漏表现自己,因为每次在Fragment中调用onCreateView时,新视图都会膨胀.

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;
    }
}

我还是Fragments的新手,并不是原始编码工作的一部分,所以我不确定我的解决方案是否正确,但它类似于我在List活动中多次实现的视图持有者模式.我真的很感激有关以下实施的任何反馈,所以我会更加放心,这是正确的.

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,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;
}
}

我没有包含与此代码相关的其他类,特别是FragmentActivity和FragmentPagerAdapter,因为它们似乎正确实现,但如果请求我也可以包含它们.

解决方法

一般来说,Android应用程序中的内存泄漏

你确定它是在泄漏内存而不仅仅是延迟垃圾收集吗?您是否在应用程序上运行eclipse内存分析器插件?它通常可以准确显示泄漏发生的位置.

片段viewpager及其回收(或缺乏)

我对片段寻呼机内存泄漏/增加的第一个猜测是拥有一个动态适配器. fragmentpageradapter非常愚蠢,无法很好地处理更改.

据我所知,从源头看它永远不会破坏碎片,即使你将数量从5改为4(第五个碎片将保留在碎片管理器中).这是因为它被分离而不是被破坏.但是,当它们位于页边距之外时,fragmentstatepageradapter将销毁它们.

从长远来看,所有这些都不会导致内存泄漏,因为当片段管理器稍后清除片段时,这些片段将被清除.然而,它可以相当多地增加内存使用(可能导致outofmemoryerror).

确实每次创建片段时都会创建一个新视图(如果将retaininstance设置为true,则通常会创建新视图),但除非您使用FragmentStatePagerAdapter,每个片段只应出现一次,因为正常的寻呼机适配器会分离并附加相同的片段来自片段管理器.在任何情况下,视图将在活动被销毁后处理,除非您保留对它的引用.

你似乎确实在你的课程中保留了对视图的引用,这是我通常试图避免的.我更喜欢在需要时使用getView().findViewById(),但在这种情况下,我认为gc会找到并删除成员引用.这一切都取决于你当然是否泄漏了那些参考文献.

在片段寻呼机中的观察者

您不应该尝试像片段中的视图符号那样执行某些操作.在这个例子中它可能不会受到伤害,但我看不到你从中获得任何东西.只需在oncreateview中膨胀视图并设置值并完成它.

列表视图中没有回收视图,因此ViewHolder模式没有任何意义,只会因为悬空引用而引入内存泄漏或延迟垃圾收集.

视图不会被重用,即使它们可以在您使用过的某些父级技巧中进行.这应该只是作为最后的出路.如果在流程中有任何关闭,它可能会导致可怕的泄漏.

如果有人能够合理使用它,请纠正我.

关于ViewHolder的旁注

我实际上不会使用viewholder,除非我真的需要它甚至在listview中.我已经看到这些标签导致真正令人讨厌的内存泄漏,例如一些游标适配器,我会在尝试引用保存之前考虑使我的行布局更简单. Findviewbyid在良好的布局中不会那么昂贵.

猜你在找的Android相关文章