gpt4 book ai didi

android - 这是使用 Kotlin 在类中实例化对象的好方法吗?

转载 作者:行者123 更新时间:2023-12-02 12:38:15 25 4
gpt4 key购买 nike

我总是在 CameraX 项目中找到类似于代码 A 的代码。它使用类内 companion object 内的对象创建实例。

如果我写相同的代码,我会使用代码 B。

用 Kotlin 实例化一个类中的对象是不是一种好方法?代码 A 是否优于代码 B?

顺便说一句,我不认为“每个 Fragments 类都必须有一个空的构造函数”。您可以考虑使用普通类而不是 Fragments 类吗?

代码A

class UIFragmentPhoto internal constructor() : Fragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?) = ImageView(context)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val args = arguments ?: return
val resource = args.getString(FILE_NAME_KEY)?.let { File(it) } ?: R.drawable.ic_photo
Glide.with(view).load(resource).into(view as ImageView)
}

companion object {
private const val FILE_NAME_KEY = "file_name"

fun create(image: File) = UIFragmentPhoto().apply {
arguments = Bundle().apply {
putString(FILE_NAME_KEY, image.absolutePath)
}
}
}
}

调用A

override fun getItem(position: Int): Fragment = UIFragmentPhoto.create(mediaList[position])

代码 B(已修改)

class UIFragmentPhoto internal constructor() : Fragment() {
val FILE_NAME_KEY = "file_name"

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?) = ImageView(context)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val args = arguments ?: return
val resource = args.getString(FILE_NAME_KEY)?.let { File(it) } ?: R.drawable.ic_photo
Glide.with(view).load(resource).into(view as ImageView)
}


constructor(image: File):this(){
arguments = Bundle().apply {
putString(FILE_NAME_KEY, image.absolutePath)
}
}

}

调用 B(已修改)

override fun getItem(position: Int): Fragment = UIFragmentPhoto(mediaList[position])

最佳答案

如果是 fragment :

根据android.googlesource.comFragment类的源代码在定义默认构造函数的地方,我们看到:

Every fragment must have an empty constructor, so it can be instantiated when restoring its activity's state. It is strongly recommended that subclasses do not have other constructors with parameters, since these constructors will not be called when the fragment is re-instantiated; instead, arguments can be supplied by the caller with setArguments and later retrieved by the Fragment with getArguments.

Applications should generally not implement a constructor. Prefer onAttach(Context) instead. It is the first place application code can run where the fragment is ready to be used - the point where the fragment is actually associated with its context. Some applications may also want to implement onInflate to retrieve attributes from a layout resource, although note this happens when the fragment is attached.


引用上述原因,在Fragment中添加非默认构造函数PROHIBITED!!!

之后,使用 setArgumentsgetArguments 方法是避免添加额外构造函数的替代方法。有问题的代码B同时使用了这两种方法。您应该使用其中之一,例如代码A。 (因为当您将参数传递给构造函数时,可以在类中访问它。因此不需要 [set/get]Arguments 模式)

但是,如果我们想在不使用参数的情况下重写代码B(免责声明:我强调这种做法是不正确的),我们可以像下面这样:

class UIFragmentPhoto internal constructor(private val image: File?) : Fragment() {

constructor() : this(null)

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?) = ImageView(context)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val resource = image ?: R.drawable.ic_photo
Glide.with(view).load(resource).into(view as ImageView)
}

}


总的来说:

我们都知道在Java/Kotlin中通过调用类的构造方法来创建对象。例如:

val obj = MyClass()

当你想创建一个对象时,没有必要将构造函数调用包装在另一个函数中,除非对象的性质必须根据程序的性质而改变。因为它会导致增加一个额外的函数调用的负担来创建一个没有任何优势的对象。

在对象根据程序的性质不断变化的情况下,我们必须借助创建型设计模式来提供更通用和更灵活的方法(如:工厂方法、抽象工厂、 等等模式)。


结论:

  1. 当您处理从 Fragment 类创建对象时,应使用 Code A 样式。 (因为android.googlesource.com中描述的原因)

  2. 当您处理从Fragment 类创建对象时,Code B 风格更适合使用。 (因为避免了没有优势的额外函数调用)


关于android - 这是使用 Kotlin 在类中实例化对象的好方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58585384/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com