- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
由于内存泄漏,我一直在重新编写一些代码。该代码是应用程序帮助部分的一部分,我们在其中使用 FragmentActivity 和 FragmentPageAdapter 允许用户滑动不同的帮助屏幕。每个 fragment ,下面的 SectionFragment 类,包括一个图像、一些标题文本和正文文本。
内存泄漏本身就是因为每次在 Fragment 中调用 onCreateView 时都会膨胀一个新 View 。
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 还是个新手,也不是最初编码工作的一部分,所以我不确定我的解决方案是否正确,但它类似于我在列表 Activity 中多次实现的 View 持有者模式。我非常感谢对以下实现的任何反馈,所以我会更放心这是正确的。
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;
}
}
我没有包含与此代码关联的其他类,特别是 FragmentActivity 和 FragmentPagerAdapter,因为它们似乎已正确实现,但如果需要,我也可以包含它们。
最佳答案
您确定它正在泄漏内存而不仅仅是延迟垃圾收集吗?您是否在应用程序上运行过例如 eclipse 内存分析器插件?它通常可以准确显示泄漏发生的位置。
我对 fragment 寻呼机内存泄漏/增加的第一个猜测是有一个动态适配器。 fragmentpageradapter 非常笨,不能很好地处理变化。
据我从源代码中所见,即使您将计数从 5 更改为 4,它也永远不会销毁 fragment (第五个 fragment 将保留在 fragment 管理器中)。这是因为它被分离而不是被摧毁。 fragmentstatepageradapter 会在 View 超出页边距时破坏 View 。
从长远来看,所有这些实际上并不会导致内存泄漏,因为当 fragmentmanager 稍后清除 fragment 时,这些 fragment 将被清除。但是,它会增加内存使用量(可能导致内存不足错误)。
每次创建 fragment 时都会创建一个新 View (如果将 retaininstance 设置为 true,则创建的次数会更多),但除非您使用 FragmentStatePagerAdapter,因为正常的寻呼机适配器会分离和附加,所以每个 fragment 应该只出现一次来自 fragment 管理器的相同 fragment 。在任何情况下, View 都将在 Activity 被销毁后被释放,除非您保留对它的引用。
您似乎确实在类里面保留了对 View 的引用,这是我通常尽量避免的事情。我更喜欢在需要时使用 getView().findViewById(),但在这种情况下,我认为成员引用应该由 gc 找到并删除。当然,这完全取决于您是否在其他地方泄漏了这些引用。
您不应该尝试在 fragment 中做类似 viewholder 的事情。在这个例子中它可能不会受到伤害,但我看不到你从中获得任何好处。只需在 oncreateview 中扩充 View 并设置值即可。
没有 View 的回收,例如在 ListView 中,因此 ViewHolder 模式没有意义,只会冒引入内存泄漏或由于悬空引用而延迟垃圾回收的风险。
View 不是为了重复使用而设计的,即使它们可能会像您使用的那样在某些父欺骗期间被重复使用。这只能作为最后的出路。然而,如果流程中有任何问题,它可能会导致可怕的泄漏。
如果有人可以合理使用它,请纠正我。
关于 ViewHolder 的旁注
我实际上会避免使用 viewholder,除非我真的需要它,即使在 ListView 中也是如此。我已经看到这些标签在某些游标适配器中导致非常严重的内存泄漏,我会在尝试引用保存之前考虑使我的行布局更简单。 Findviewbyid 在良好的布局中不会那么昂贵。
关于android - 仔细检查 fragment + view holder 模式是否正确实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9933783/
我有一个画廊,每个元素都有 .item 类。在 .item 中总有一个删除它的链接: Title of item remove 当您按下一个 .item 时,它会显示一个红色边框 div.item:a
一 点睛 Hold 方式的单例完全是借助了类加载的特点。 二 代码 package singleton.singleton3; // final 不允许继承 public final class S
所以,这是我的项目结构。这只是一个两个选项卡的应用程序。 左侧选项卡上有所有可用项目的列表。在右侧选项卡上,有用户最喜欢的项目的列表。每个项目都有一个按钮,单击该按钮,该项目就会成为 Collecti
我正在使用 jBullet 和 OpenGL 来创建一个基本的游戏引擎。我创建了两个名为 ObjectSurface 和 ObjectEntity 的类。基本上,ObjectSurface 没有质量,
我正在开发具有自定义布局 和arrayAdapter 的应用。我的自定义布局由 1 个 ImageView、2 个 textView 和 1 个复选框组成。 Booth 的图像文件和文本存储在 val
我正在实现一个模板类“Holder”,稍后应该专门用于包含不同类的对象。 Holder 将对象存储为属性。当在构造函数中存储需要参数的对象时,holder 类在实例化时失败: #include te
我有带部分的列表,但是这个 ListView 很慢。 我需要任何支架,但我不知道怎么做。 当我只有一种 View 时很简单,但在这里我遇到了问题。 我创建了 holder,但是当 ListView 显
在我的应用程序中,我有几种holder 对象,其主要目的是存储异构相关数据。它们的生命周期可以分为两部分: 一旦可用就收集数据; 在持有人的余生中提供对存储数据的只读访问权限。 使持有者不可变是非常诱
我正在将数据上传到服务器,如果数据成功上传到服务器,那么我会显示“已保存”,就像您可以看到图像“已上传”一样。 但问题是,我已经为第一个项目行存储了数据,而在不同的行项目中获取“已保存”文本 hold
我有一个杂乱的树形多维数组,我想执行以下操作: 提取每个数组,无论嵌套多远以将其放入单个“holder 数组”,所以这(只是一个基本示例,因为就嵌套而言它会比这复杂得多) $this = array[
我有两个版本的“Initialization-on-demand holder idiom”: http://en.wikipedia.org/wiki/Initialization-on-deman
我正在开发自定义相机应用程序。下面是我的 Activity 类。 public class MyCustomCam extends Activity { private Camera mCamera;
我对 ListView 有问题,或者更准确地说 - 放置在其上的 ImageView。我的应用正在从 Youtube 下载缩略图。到那个地方的一切都很好。后来,在使用 getView() 时出现了一个
使用 CSS,如何根据下图创建部分边框 我可以获得完整的边框: border: 1px solid #f5f5f5; 但只想在垂直边框的顶部和底部显示 30px,中间没有任何东西? 这能实现吗? 一如
以下代码将 Holder 指定为 interface 类型。 可以对 Holder 对象进行哪些更改,以便它接收具有引用类型的任何类型,因此如果对值对象进行任何更改,它会反射(reflect)在 ma
我正在开发一个具有自定义布局和 arrayAdapter 的应用: 问题是当我选中一个框时,应用程序会自动选中另外2个框! 我创建了一个列表,在其中放置了复选框的位置,并表明没有任何问题!我认为问题出
我有一个非常简单的单例,它使用持有者模式(我只显示了模式,没有其他细节): public class Foo { private static class FooHolder {
我一直在尝试使用 jQuery 构建一个简单的照片库。这是我到目前为止所得到的。这工作正常,但问题是照片没有垂直居中显示在屏幕上。 这是我正在处理的片段。如果您全屏运行代码片段,图像会停留在顶部。如何
我试图理解并完成尝试创建一个类的任务,该类扩展了一个接受所有类型类的通用类。到目前为止,我有这个工作。我正在尝试创建一个扩展通用持有人类的类,并让这个类只接受特定的对象。 例如,名为“Computer
这是网络上最常见的实现方式 private static class LazySomethingHolder { public static Something something = new S
我是一名优秀的程序员,十分优秀!