- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我总是在 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.com上Fragment
类的源代码在定义默认构造函数的地方,我们看到:
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!!!
之后,使用 setArguments
和 getArguments
方法是避免添加额外构造函数的替代方法。有问题的代码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()
当你想创建一个对象时,没有必要将构造函数调用包装在另一个函数中,除非对象的性质必须根据程序的性质而改变。因为它会导致增加一个额外的函数调用的负担来创建一个没有任何优势的对象。
在对象根据程序的性质不断变化的情况下,我们必须借助创建型设计模式来提供更通用和更灵活的方法(如:工厂方法、抽象工厂、 等等模式)。
当您处理从 Fragment
类创建对象时,应使用 Code A 样式。 (因为android.googlesource.com中描述的原因)
当您处理从非Fragment
类创建对象时,Code B 风格更适合使用。 (因为避免了没有优势的额外函数调用)
关于android - 这是使用 Kotlin 在类中实例化对象的好方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58585384/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!