18

我有一个 ListView,其中 listview 的每一行包含大约 10 个 ImageButton。这些按钮中的大多数都具有可见性 = Gone 并且仅在非常罕见的情况下出现。我想知道是否值得用 ViewStubs 替换这些 ImageButtons 以避免在列表视图的所有行中一直加载它们(以及它们包含的图像)。然后它们的可见性再次设置为“消失”,所以我不确定加载它们有什么影响。他们的图像是否真的被加载了?

请注意,我说的是用 8 个 ViewStubs 代替例如 8 个 ImageButtons,而不是用 1 个

干杯

4

7 回答 7

11

AViewStub是一个dumb and lightweight视图。它有no dimension,它不绘制任何东西,也不以任何方式参与布局。这意味着 aViewStub非常cheap to inflate and very cheap to keep处于视图层次结构中。AViewStub可以最好地描述为lazy include。a 引用的布局ViewStubinflated and added适用于用户界面when you decide

有时您的布局可能需要complex views很少使用。无论它们是项目详细信息、进度指示器还是撤消消息,您都可以通过仅在需要时加载视图来减少内存使用并加快渲染速度。

简单的 aViewStub用于提高渲染布局的效率。通过使用ViewStub,可以手动创建视图,但不能将其添加到视图层次结构中。在运行时,可以很容易地被充气,而ViewStub被充气时,viewstub将替换viewstub.

只有在ViewStub您实际使用它/需要它时才会加载,即,当您将其可见性设置为VISIBLE(实际可见)或INVISIBLE(仍然不可见,但其大小不再为 0)时。ViewStubanice optimization因为你可以在任何地方拥有一个复杂的layout with tons of small views or headers,并且仍然拥有你的Activity load up really fast. 一旦您使用其中一个视图,它将被加载。

您必须先添加ViewStub布局,然后才能将其膨胀到另一个视图。

注意:它的一个缺点ViewStub是它目前不支持<merge/>布局中的标签被充气。阿洛斯ViewStub不能多次使用。同样保持对 a 的长期引用ViewStub是不必要的,如果需要,最好在充气后将其设为空,这样GC可以吃掉它。

假设您的ViewStubID 是view_stub. 您需要在 中执行以下操作activity

ViewStub viewStub = (ViewStub) findViewById(R.id.view_stub);
View inflatedView = viewStub.inflate();
ImageButton button = (ImageButton) inflatedView.findViewById(R.id.button);

现在您可以使用按钮做任何您想做的事情了:)也就是说,inflate 方法返回包含 XML 文件中实际元素的存根布局。

当然,您可以始终拥有onClickXML 属性或者可以动态调用。

Is a ViewStub worth it?
->For the scenarios that you are specifying, I think `ViewStub` will be worth-shot.  

请参阅下面的网址ViewStub

http://android-developers.blogspot.in/2009/03/android-layout-tricks-3-optimize-with.html

http://developer.android.com/reference/android/view/ViewStub.html

http://developer.android.com/training/improving-layouts/loading-ondemand.html

代替ViewStub你可以试试<\include> tag。它将只在您的基本 xml 文件中包含 xml 内容,<include/>就好像整个事情只是一个大文件一样。这是在不同布局之间共享布局部分的好方法。

android中<include>和<ViewStub>的区别

于 2015-12-31T18:55:15.447 回答
7

编辑:刚刚注意到 Endzeit 在我之前就类似的方向发表了评论。

我将首先围绕带有和不带有视图的膨胀代码进行一些基准测试 - 只需注释掉适配器代码,这样它就不会尝试访问不存在的视图。

如果从布局中删除视图确实为您提供了您认为必要的改进,并且由于您说视图仅在您在适配器中检查的罕见场景中出现,那么不要夸大这些视图甚至使用查看存根,在代码中创建它们并根据需要添加/删除它们(使用查看器来引用它们)。

你甚至可以更进一步,懒惰地创建这些视图,类似于延迟加载图像,但我只会在再次运行一些基准测试后才会这样做。

我会使用 ViewStubs 来加载复杂的布局,而不是简单的 ImageButtons。

编辑2:

查看 ViewStub inflate 命令,这是它在需要可见时所做的事情,您可以看到它使给定的布局膨胀,然后将其添加到父布局中 - 因为您正在添加一个简单的 ImageButton,您可以通过没有 ViewStub 来获得性能只需在代码中添加 ImageButton 即可。 http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/view/ViewStub.java#ViewStub.inflate%28%29

于 2015-12-31T18:50:34.727 回答
4

根据谷歌的官方文档here

ViewStub 是一个没有维度的轻量级视图,它不绘制任何东西或参与布局。因此,膨胀和留在视图层次结构中很便宜。每个 ViewStub 只需要包含 android:layout 属性来指定要膨胀的布局。

为了对此进行试验,我创建了一个示例项目并将 ViewStub 添加到布局层次结构中。在运行布局检查器时,我可以看到 ViewStub 的所有布局属性都为零。

在此处输入图像描述

让我们将其与隐藏 10 个按钮的布局进行比较。这实际上意味着,布局层次结构隐藏了 10 个按钮,它们位于布局层次结构中并占用了一些内存。将 ViewStub 保留在层次结构中很便宜,因为它不会占用太多内存,同时膨胀也很便宜。

我的最终结论是,当您拥有很少膨胀的复杂视图时,广泛使用 ViewStub,因为它肯定有助于节省内存和改善视图膨胀时间。

于 2017-10-12T17:12:47.243 回答
2

在 Android Studio 中使用 Android 监视器的 Memory 选项卡(Android 监视器的按钮应该在底部栏),您可以自己检查:

  • 使用隐形按钮运行应用程序时查看内存使用情况
  • 使用可见按钮运行应用程序时查看内存使用情况

如果有任何区别,那么您可以得出结论,当视图消失时,并非所有内容都已预加载。当然,您也可以将其与 ViewStub 实现进行比较,以检查这是否有助于减少内存使用。

于 2016-01-06T09:06:01.030 回答
2

简而言之,使用自定义视图而不是viewstub。

我们现在也有类似的情况,我们之前也试过viewstub,listview工作的快一点。但是当涉及到 8 个视图时,我认为使用视图来避免膨胀过多的小部件并不是一个好主意。

既然你(还有我们)有一个逻辑来控制是否显示 10 个按钮,为什么不直接定义一个自定义视图,并根据不同的状态机绘制不同的按钮呢?它速度快得多,根本不需要通货膨胀,而且它的逻辑控制得更好。我们现在正在使用这种方法来加速列表视图,并且效果很好。

于 2016-01-07T10:59:55.860 回答
1

当您将视图可见性设置为消失时,这意味着此视图是不可见的,并且它不占用任何布局空间,但其数据已加载到其中。

现在 ListViews 他们删除了看不见的,或者说出于性能原因超出屏幕范围的视图。

ViewStub 是一个不可见的、大小为零的视图,可用于在运行时懒惰地膨胀布局资源

所以我想如果你想从我的观点来看,我更喜欢带有 GONE Visibility 的视图,而不是使用 ViewStub 和创建和膨胀......等的大量逻辑。

但另一方面

当您膨胀视图时,渲染性能就会显现出来。

我的猜测是,膨胀 ViewStub 比膨胀视图便宜得多,无论是从 XML 还是通过改变可见性。当您需要添加/删除(不确定的)视图(例如,将电话号码添加到给定的联系人)时,特别使用 ViewStub。希望这就是你要找的。

参考:ViewStub 与 View.GONE

DDMS 的一些很好的简要介绍:http: //magicmicky.github.io/android_development/benchmark-using-traceview/

于 2015-12-31T18:21:46.320 回答
-1

使用 ViewStub 代替 ImageButton。

这是因为

. 默认情况下 ViewStub 是零大小的视图,而图像按钮不是

. View Stub 自然是一个无形的视图。它的性能优于图像按钮,因为它仅在其状态可见时才加载运行时。

于 2015-12-29T14:01:32.153 回答