android-fragments 有人能解释一下这两种用法的区别吗?我知道碎片膨胀,但另一种用法令人困惑,两者是一样的吗?

du7egjpx  于 2022-11-13  发布在  Android
关注(0)|答案(2)|浏览(141)

此代码段已在活动(onCreate)中使用:

binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

此代码段用于片段(onCreateView):

cameraView = inflater.inflate(R.layout.fragment_camera_view, container, false)
    return cameraView
vzgqcmou

vzgqcmou1#

setContentView是一个 * Activity * 显示其视图层次结构的方式。你可以自己膨胀层次结构并将其传递进来(就像你在这里所做的,使用binding.inflate,然后传递得到的binding.root),或者你可以调用setContentView(R.layout.some_layout),它将负责膨胀布局本身。
onCreateView是一个 * Fragment * 方法,它在Fragment初始化时被调用,并且它需要创建它的视图层次结构。所以你需要覆盖它,膨胀你的层次结构,然后在最后返回它,这样Fragment就可以使用它了。
因此,setContentViewActivity中被调用,并且可以接受布局引用或View s的实际膨胀集。onCreateViewFragment中的一个方法,在该方法中,您需要返回View s的膨胀集。
当你要真正地“膨胀”这些View时,你有几个选择。你的例子都使用了不同的方法--所以除了一个是Activity,一个是Fragment,你做的事情不同之外,你还混合和匹配了你膨胀东西的方式。
扩展布局的标准方法是获取一个LayoutInflater并在其上调用inflate,传递一个布局XML文件,这样它就可以使用该文件创建所有必需的View对象并将它们连接在一起:

// Typically in an Activity you'd use 'this' as the Context, since an Activity -is- a Context
// In a Fragment's onCreateView you get an inflater passed in, in a RecyclerView.Adapter's
// onCreateViewHolder you have access to the 'parent' which you can grab a Context from, etc
val inflater = LayoutInflater.from(context)

// Inflate an XML file - the second parameter is the parent container, used for working out
// things like layout parameters (e.g. to make 'match_parent' work).
// The last parameter is about attaching the View you're inflating - this is usually false!
// We're handing off the View, the thing that's using it will handle attaching it
val view = inflater.inflate(R.layout.some_layout, container, false)

就是这样!现在你有了一堆实际的View,你可以把它们拿出来展示。

// in your activity
setContentView(view)

// at the end of onCreateView
return view

如果你使用 View Binding,你通常不想直接使用LayoutInflater。生成的绑定类(例如ActivityMainBinding)有一个inflate调用,它使用相关的XML文件为你做膨胀,然后它创建一个 *binding对象 *,其中包含该膨胀层次结构中所有View对象的变量。
这样你就不需要用findViewById来查找任何东西了--这基本上已经为你做好了,你可以用binding.someId来访问它们。绑定对象也保存了膨胀的层次结构,你可以用binding.root来访问它。你可以用和以前一样的方法传递它来显示:

// in your activity
setContentView(binding.root)

// at the end of onCreateView
return binding.root

你在ActivityFragment中做的事情是不同的,但是你膨胀视图的方式是相同的--这取决于你在做什么,如果你使用 View Binding,那么你将使用绑定类而不是inflater.inflate
为了完整起见,你也可以使用bind方法,从一个已经膨胀的视图层次结构中创建一个绑定对象--例如ActivityMainBinding.bind(view)。如果已经处理了膨胀,那么这是很有用的,所以你想跳过这一步,只需要查找所有的视图,然后得到你的绑定对象。

请记住,如果您再次扩大布局,您将得到一组完全不同的对象,并且如果您显示那些您无法看到或与原始对象交互的对象。通常,您只希望扩大布局一次-拥有两组视图是您犯了错误的标志,并可能导致诸如“为什么我的点击监听器不工作”(您在替换的其他视图上设置了它们)等错误。

布局可能已经膨胀的典型情况是,使用ActivityFragment构造函数时,将布局XML资源作为参数提供,比如class MainActivity : AppCompatActivity(R.layout.activity_main)。当你调用super.onCreate()时,它会处理setContentView位(如果onCreate只是这样做的话,您可能根本不需要覆盖它!)要创建绑定对象,您只需要将bind设置为Activityview属性。
对于Fragment也是一样的--你可以把布局文件放在构造函数中,那么就不需要重写onCreateView了,因为这一切都已经处理好了。

oalqel3c

oalqel3c2#

使用Binding而不是直接膨胀的原因有以下几点:

*运行时性能:使用直接膨胀findViewById()执行视图层次结构的自上而下搜索,直到找到匹配。它没有优化,也没有内部缓存,所以如果我们使用相同的视图ID快速连续调用该方法两次,那么两次调用都需要相同的自上而下搜索。使用绑定时,不存在访问ActivityMainBinding示例的text1字段的隐藏成本。
*避免碰撞:有时候,如果我们在Android生命周期中过早地访问Kotlin合成视图属性,在它们初始化之前,我们会遇到崩溃。尽管仍然有必要在Android生命周期的正确阶段执行布局和绑定的膨胀,该初始化实际上将在Activity或Fragment代码中完成,从而使其在生命周期中的初始化正在发生。
*构建时间:运行时性能的提高会在构建时产生成本,因为它使用代码生成。它还会增加APK的大小和方法数量。

参考:https://blog.stylingandroid.com/view-binding-internals/

相关问题