ViewStub与View.GONE与Inflate与ViewSwitcher的区别

12

我有一个与懒加载视图/布局性能相关的问题。 有时我们想动态显示/隐藏多个视图。在这种情况下,我们有四个选择:

  1. 将所有布局包含在.xml中,并使用setVisibility方法(如View.GONE和VIEW.VISIBLE)
  2. 使用ViewFlipper / ViewSwitcher
  3. 使用ViewStub
  4. 通过编程方式填充新布局。

哪一个拥有最佳性能? 我已经Google了一番,发现ViewStub是专为此设计的,但我不确定。也许我错了,或者甚至有第五个选项我不知道。您对此有不同的观点或经验吗?谢谢!

2个回答

10

这取决于您想要填充的视图。每种方法都有自己的开销,您需要决定在哪里做出妥协。

  1. 如果您的视图非常简单且不需要初始化过多内容,请将其设置为 View.GONE。如果它非常复杂或者布局最好不要这样做。
  2. ViewFlipperViewSwitcher 用于在不同视图之间进行动画切换。它的目的不是显示和隐藏单个视图。如果您需要在同一位置不同时间显示不同的视图,请使用它。
  3. ViewStub 只是一个占位符,它会用更复杂的布局替换自己。
  4. 手动完成所有操作就像使用 ViewStub 一样,只是没有布局信息。如果您需要以编程方式创建或设置视图,则可能是一个不错的选择。

6

2017年,Android团队在支持库v24上发布了AsyncLayoutInflater。2020年,它成为Jetpack库的一部分(链接)

AsyncLayoutInflater是一种惰性膨胀布局的另一种方式。正如API文档所说:

用于异步膨胀布局的辅助类。要使用,请在UI线程上构造AsyncLayoutInflater的实例并调用inflate(int、ViewGroup、OnInflateFinishedListener)。当膨胀请求完成时,将在UI线程上调用AsyncLayoutInflater.OnInflateFinishedListener。

这适用于惰性创建或响应用户交互的UI部分。这样,UI线程就可以继续响应和动画,而相对较重的膨胀正在执行。

以下是使用AsyncLayoutInflater的代码片段:

button.setOnClickListener { view ->
    val container = findViewById(R.id.container)
    val asyncLayoutInflater = AsyncLayoutInflater(this@MainActivity)
    asyncLayoutInflater.inflate(
        R.layout.view_sample,
        container,
        object : OnInflateFinishedListener() {
            fun onInflateFinished(view: View, resId: Int, parent: ViewGroup) {
                parent.addView(view)
            }
        }
    )
}

1
还应考虑 https://medium.com/@gajendratwinwal/asynclayoutinflater-android-performance-e2fd3e0f908b 相关内容。 - necip
我认为普通的LayoutInflaters可以懒初始化而不会出现问题……至少RecyclerViews已经这么做了很长时间了。 也许这将把oneShotPreDrawListener合并成一个对象或类似的东西……我不明白为什么他们从未制作处理视图状态的组件,以便于对具体类型进行适配器。mutableContainer.set(adapter);其中adapter为: Adapter<MyEnum> adapter = Adapter.get((inflater, myEnum) -> { //returns aView});以便于我们通过适配器交换和控制视图… - Delark
哦,算了吧,我现在注意到它执行了“前后”(从后台到前台线程)管理。如果他们的ArchTaskExecutor类可以处理这种情况,那么这并不难实现,在单个方法中就可以实现...但是它能处理背压丢失吗? - Delark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接