如果片段+观点持有者模式是正确实施双重检查 [英] Double checking if fragment + view holder pattern is implemented properly

查看:168
本文介绍了如果片段+观点持有者模式是正确实施双重检查的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直再努力一些code由于内存泄漏。在code是,我们使用的是FragmentActivity和FragmentPageAdapter允许用户刷卡通过不同的帮助,屏幕上的应用程序帮助部分的一部分。每一个片段,下面SectionFragment类,包括图像,一些标题文本及正文。

I've been re-working some code due to a memory leak. The code is part of the apps help section where we are using a FragmentActivity and FragmentPageAdapter to allow the user to swipe through the different help screens. Each fragment, SectionFragment class below, includes an image, some header text and body text.

内存泄漏表现出来,因为一个新的观点被各onCreateView被称为在碎片时间膨胀。

The memory leak manifested itself because a new view was being inflated each 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;
    }
}

我还是新来的碎片,是不是原来的编码工作,所以我不知道,我的解决方案是正确的一部分,但它就像我在清单活动实施多次的观点持有人格局。我真的AP preciate以下实施任何反馈,这样我会更舒服,这是正确的。

I'm still new to Fragments and wasn't part of the original coding effort so I'm not sure that my solution is correct, but it resembles the view holder pattern I've implemented many times in List Activities. I'd really appreciate any feedback on the following implementation so I'd be more comfortable that this is 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;
}
}

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

I haven't included the other classes associated with this code, specifically the FragmentActivity and FragmentPagerAdapter because they seem to be implemented properly, but if requested I can also include them.

推荐答案

您确信这是泄漏内存,而且不只是延缓了垃圾收集?你有没有运行,如Eclipse内存分析器插件的应用程序?它往往能准确显示其中出现泄漏。

On memory leaks in Android apps in general

Are you certain that it was leaking memory and not just delaying the garbage collection? Have you run for example eclipse memory analyzer plugin on the application? It can often show exactly where the leaks occur.

我的第一个猜对内存泄漏/增加一个片段寻呼机有一个动态的适配器。该fragmentpageradapter是pretty的愚蠢和将不予办理变更以及

My first guess for memory leaks/increases in a fragment pager is having a dynamic adapter. The fragmentpageradapter is pretty dumb and will not handle changes well.

据我可以从源头上看到它永远不会摧毁的碎片,即使你如改变从5到4计数(第五片段会留在片段管理器)。这是由于它被分离的,而不是破坏。在 fragmentstatepageradapter 但是会破坏意见时,他们的页边距之外。

As far as I can see from the source it will never destroy fragments even if you for example change count from 5 to 4 (the fifth fragment will stay in the fragment manager). This is due to it being detached rather than destroyed. The fragmentstatepageradapter will however destroy views when they are outside of the page margin.

而这一切实际上并不导致从长远来看,内存泄漏,因为这些碎片将被清理时,fragmentmanager被清除碎片后。但是,它可以提高内存的使用相当多的(可能导致OutOfMemoryError错误)。

And all of this does not actually lead to memory leaks in the long run since those fragments will be cleaned up when the fragmentmanager is cleared of fragments later. It can however increase the memory use quite a bit (potentially leading to an outofmemoryerror).

有一个新的看法确实就产生的片段,每次(比这更多的时候,如果你设置retaininstance为true),但除非你使用FragmentStatePagerAdapter应该只发生一次每个片段,由于正常的寻呼机适配器分离,重视从片段经理相同的片段。在任何情况下,除非以后你保持引用它的活性被破坏的观点将被全部销毁。

A new view is indeed created each time the fragment is created (and more often than that if you set retaininstance to true), but unless you use the FragmentStatePagerAdapter that should only occur once per fragment since the normal pager adapter detaches and attaches the same fragments from the fragment manager. And in any case the view will be disposed after the activity is destroyed unless you keep references to it.

您似乎保持你的类,这是我通常尽量避免提到的观点。我用getView()。findViewById(),当我需要他们preFER,但在这种情况下,我想成员引用应该被发现和被GC删除。这一切都取决于你是否泄漏的其他地方引用,当然。

You do seem to keep references to views in your class, which is something I normally try to avoid. I prefer using getView().findViewById() when I need them, but in this case I think the member references should be found and removed by the gc. This all depends on if you leak those references elsewhere of course.

您不应该试图做类似的片段viewholder。它可能不会伤害在这个例子中,但我看不到你获得的任何东西。只是在膨胀的oncreateview查看和设置的值,并用它做。

You should not try to do something like the viewholder in the fragment. It will probably not hurt in this example, but I can't see you gaining anything from it. Just inflate the view in oncreateview and set the values and be done with it.

有没有回收利用的意见,如列表视图,所以ViewHolder模式是没有意义的,只有风险引入内存泄漏或延迟垃圾回收由于悬空引用。

There is no recycling of views such as in the listview, so the ViewHolder pattern makes no sense and only risks introducing memory leaks or delayed garbage collections due to dangling references.

视图不会作出重新使用,即使它们可能是在一些父诡计作为已使用。这应该只完成作为了最后的方式。如果有什么是关闭的流可以但是会导致可怕的泄漏。

Views are not made to be reused, even though they can be during some parent trickery as you have used. This should only be done as a final way out. If anything is off in the flow it can however lead to horrible leaks.

请纠正我,如果任何人都可以看到一个合理的利用它。

Please correct me if anyone can see a reasonable use for it.

上ViewHolder旁注

我真的使用viewholder避免,除非我真的需要它甚至在ListView。我看到这些标签会导致真正讨厌的内存泄漏,例如一些光标适配器,我想看看让我排布局试图引用保存前简单。 Findviewbyid不会贵在一个良好的布局。

I would actually refrain from using viewholder unless I really needed it even in a listview. I have seen those tags lead to really nasty memory leaks in for example some cursor adapters and I would look at making my row layouts simpler before trying reference saving. Findviewbyid will not be that expensive in a good layout.

这篇关于如果片段+观点持有者模式是正确实施双重检查的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆