Android - ViewStub 值得吗?

Android - Is a ViewStub worth it?

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

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

干杯

使用 ViewStub 代替 ImageButton。

这是因为

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

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

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

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

ViewStub 是一种不可见的 zero-sized 视图,可用于在运行时延迟扩充布局资源

所以我想如果你想从我的观点来看我更喜欢 Views with GONE Visibility 而不是使用 ViewStub 和 Creating and inflating ... 等的大量逻辑。

但另一方面

The rendering performance comes into picture when you are inflating the views.

My guess is that its much cheaper to inflate a ViewStub than to inflate a View, either from XML or by changing visibility. ViewStub is especially used when you need to add/remove (indefinite) views (eg. add phone numbers to a given contact). Hope this is what you were looking for.

参考:ViewStub vs. View.GONE

这里有一些不错的 DDMS 简要介绍: http://magicmicky.github.io/android_development/benchmark-using-traceview/

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

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

如果从布局中删除视图确实给您带来了您认为必要的改进,并且由于您说视图仅出现在极少数情况下,您无论如何都会在适配器中检查这些情况, 然后不要膨胀这些视图甚至使用视图存根,而是在代码中创建它们并 add/remove 根据需要(使用视图持有者引用它们)。

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

我会使用 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

一个 ViewStub 是一个 dumb and lightweight 视图。它有no dimension,它不绘制任何东西,也不以任何方式参与布局。这意味着 ViewStub 在视图层次结构中非常 cheap to inflate and very cheap to keepViewStub 最好描述为 lazy includeViewStub 引用的布局对用户界面来说只是 inflated and added when you decide 如此。

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

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

中定义的布局

ViewStub只会在你真正使用it/need时加载,即当你设置它的可见性为VISIBLE(实际可见)或INVISIBLE(仍然不可见,但它的大小不再为 0)。 ViewStub 一个 nice optimization 因为你可以在任何地方有一个复杂的 layout with tons of small views or headers,并且仍然有你的 Activity load up really fast。一旦您使用这些视图之一,它就会被加载。

必须先在Layout中添加ViewStub,然后inflate到另一个View。

注意: ViewStub 的一个缺点是它目前不支持布局中的 <merge/> 标签被放大。 Alos ViewStub 不能使用多次。同样保持 long-lived 对 ViewStub 的引用是不必要的,如果需要,最好在膨胀后将其设为 null,这样 GC 就可以吃掉它。

假设您的 ViewStub ID 是 view_stub。您需要在 activity 中执行以下操作:

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

现在你可以用按钮做任何你想做的事:)也就是说,膨胀方法returns存根布局,它包含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

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

Difference between <include> and <ViewStub> in android

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

  • 查看运行带有不可见按钮的应用
  • 时的内存使用情况
  • 查看 运行 带有可见按钮的应用程序
  • 时的内存使用情况

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

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

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

既然你(还有我们)有控制10个按钮是否显示的逻辑,为什么不定义一个自定义视图,根据不同的状态机绘制不同的按钮呢?它非常快,根本不需要 inflation,而且它的逻辑控制得更好。我们现在正在用这个方法来加速listview,效果很好。

根据Google的官方文档here

ViewStub is a lightweight view with no dimension that doesn’t draw anything or participate in the layout. As such, it's cheap to inflate and cheap to leave in a view hierarchy. Each ViewStub simply needs to include the android:layout attribute to specify the layout to inflate.

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

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

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