Android - ViewStub值得吗?

时间:2015-12-29 13:32:23

标签: android performance viewstub

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

请注意,我正在谈论更换,例如带有8个ViewStub的8个ImageButtons,而不是1个

干杯

7 个答案:

答案 0 :(得分:9)

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/>标记。 Alos 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

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

Difference between <include> and <ViewStub> in android

答案 1 :(得分:4)

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

答案 2 :(得分:2)

在Android Studio中使用Android显示器的“内存”选项卡(Android显示器的按钮应位于底部栏),您可以自行查看:

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

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

答案 3 :(得分:2)

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

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

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

答案 4 :(得分:2)

根据Google的官方文档here

  

ViewStub是一个轻量级视图,没有任何尺寸,不会绘制任何内容或参与布局。因此,在视图层次结构中离开和廉价离开是很便宜的。每个ViewStub只需要包含android:layout属性来指定要膨胀的布局。

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

enter image description here

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

我的最终结论是,当你复杂的观点很少被夸大时使用ViewStub很少,因为它肯定有助于节省内存和改善View膨胀时间。

答案 5 :(得分:1)

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

现在,ListViews会删除看不见的内容,或者说出由于性能原因而超出屏幕范围的视图。

ViewStub是一个不可见的,零大小的视图,可用于在运行时懒洋洋地扩充布局资源

所以我认为如果你想从我看来我更喜欢具有GONE Visibility的Views而不是在ViewStub和Creating and inflating等中使用很多逻辑。

但另一方面

  

当你膨胀时,渲染性能就会出现   意见。

     

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

参考:ViewStub vs. View.GONE

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

答案 6 :(得分:-1)

使用ViewStub代替ImageButton。

这是因为

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

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