【问题标题】:Android - Is a ViewStub worth it?Android - ViewStub 值得吗?
【发布时间】:2016-04-03 09:39:48
【问题描述】:

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

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

干杯

【问题讨论】:

  • 我不知道答案,但我想知道你为什么要这样做。包含一个 ViewContainer 会不会更直观,比如说一个 LinearLayout 并使用适配器将所需的图像添加到其中?这样,您的布局就不会附加不必要的视图。
  • 这个想法只是将所有视图声明保留在 xml 中,并且仅根据适配器中的要求更改元素的可见性。所以你基本上是在建议而不是改变它们在适配器中的可见性来在适配器中添加/删除它们?当我们通过 convertView 在 getView() 中重用视图时,您是否建议从该视图中删除所有内容并重新开始,或者检查那里的内容并相应地修改它?

标签: android performance viewstub


【解决方案1】:

ViewStubdumb 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,可以手动创建视图,但不能将其添加到视图层次结构中。在运行时,可以很容易地被充气,而ViewStub被充气,viewstub的内容会被viewstub中定义的布局替换。

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

你必须先在布局中添加ViewStub,然后才能将它膨胀到另一个视图。

注意:ViewStub 的一个缺点是它目前不支持要膨胀的布局中的 <merge/> 标签。阿洛斯ViewStub 不能多次使用。同样保持对ViewStub 的长期引用是不必要的,如果需要,最好在膨胀后将其设为空,这样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);

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

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

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

【讨论】:

    【解决方案2】:

    编辑:刚刚注意到 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

    【讨论】:

    • 你的最后一句话是我提出这个问题的主要关注点!我将与 TraceView 进行一些比较,看看它会把我带到哪里。干杯
    • 添加了一些解释,说明为什么在运行时添加 ImageButton 会比使用 ViewStub 更好。
    • 你能在顶部的 cmets 中看看我的问题吗?
    • 是的,这个想法是在适配器中添加/删除视图 - 在我看来这将是一种有效的方式,特别是因为您说大多数时候视图都不存在。
    • 您可以轻松检查持有者是否引用了现有的 ImageButton,然后在需要时删除或添加它并更新其内容。
    【解决方案3】:

    根据谷歌官方文档here.

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

        • 你说的是视图组吗?
        • @sakis 在我们的一个案例中,我们必须显示 6 个按钮,每个按钮对应一种状态。我们定义了一个扩展 View 类的 MyView,并在它的 onDraw 方法中绘制按钮(它只是一个带圆角的矩形)和其他类似 textview 的方法。使 MyView 可点击并响应触摸事件(获取 cilck xy 并查看它是否在矩形内)。如果我们需要任何点击效果,只需在更改 rect 的属性中添加动画即可。
        • 是的,起初我就是这么想的,然后我开始考虑点击监听器并处理所有这些:P 但是如果你有性能问题,这样做确实很有意义,那肯定会性能最好的。感谢您的澄清!
        • 我很高兴它有帮助^_^
        【解决方案6】:

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

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

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

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

        但另一方面

        当你充气时,渲染性能就会显现出来 意见。

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

        参考:ViewStub vs. View.GONE

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

        【讨论】:

          【解决方案7】:

          使用 ViewStub 代替 ImageButton。

          这是因为

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

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

          【讨论】:

          • 我稍微编辑了我的问题。我的 ImageButtons 的可见性 = Gone,所以我不确定它们的图像是否实际加载?
          • 这个案例与问题相去甚远。如果您设置视图 visibility=gone 的可见性而不是您有责任将其放回 visibility=visible 并且对于视图存根和图像按钮都是相同的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-08
          • 1970-01-01
          • 1970-01-01
          • 2011-04-01
          相关资源
          最近更新 更多