当前位置: 首页 > 知识库问答 >
问题:

Android:抽象自定义视图和通用布局膨胀

充培
2023-03-14
abstract class Foo @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    private val myView: View

    init {
        // todo@patches fix leaking "this"
        View.inflate(context, R.layout.view_foo, this)
        myView = requireNotNull(findViewById(R.id.my_view))
    }
}
class Bar @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : Foo(context, attrs, defStyleAttr) 

还有人觉得这有点令人沮丧或有什么建议吗?从基类中膨胀相同的布局似乎并不罕见。

共有1个答案

鱼安然
2023-03-14

在构造函数中泄漏是危险的,因为您泄漏到的对象可能在构造函数完成之前就开始访问其成员,因此它可能还没有准备好。即使对于不可空的Kotlin属性或其他奇怪的行为,也可以获得NPEs。

对于layoutinflator.inflate,这似乎不是一个问题,因为Android的内置视图经常将这个作为inflate()方法的父级传递给inflate()。例如,DatePicker的构造函数实例化一个DatePickerSpinnerDelegate,它将该DatePicker实例传递给invlate(),所有这些都发生在DatePicker的构造函数返回之前。

当您将视图作为父视图传递给invulate()时,通过遵循调用链,我看到父视图发生了两件事。它对父级调用getcontext(),如果addtoroot为true,则对父级调用addview()。因此,我认为泄漏这个是安全的,只要您不重写addview()来执行额外的工作,这些工作依赖于调用invalate()后设置的成员。但是addview()也在内部调用requestlayout()invalidate()`,所以同样的问题也适用于它们。

在大多数情况下,您的自定义ViewGroup将是现有Android ViewGroup类的子类,因此您不需要重写这些方法。

不幸的是,我们只能通过检查代码来推断这种行为。文档没有保证它是安全的,这并不令人放心,但据我所知,我们只能接受它可能是安全的。也许应该在AOSP上打开一个问题。如果您用Java编写相同的代码,甚至不会出现此警告,但风险是相同的。

禁止警告并不意味着您忽略了警告或只是在代码上进行黑客攻击。它的意思是,“我承认失败模式,并已经检查了我的代码不会以这种方式失败。”如果不是这样,那将是编译器错误,而不是警告。在Kotlin中,可以使用的抑制注释是@suppress(“leakingthis”)

 类似资料:
  • 一般来说,我想知道如何在运行时膨胀XML定义的自定义布局,而不在视图层次结构中使用冗余布局。 现在,特别是:

  • 问题内容: 我正在尝试使用Android中的XML文件定义GUI布局。据我所知,没有办法指定您的小部件应在XML文件中使用一种自定义字体(例如,您放置在资产/字体/中的字体),并且只能使用系统安装的字体。 我知道,在Java代码中,我可以使用唯一ID手动更改每个小部件的字体。另外,我可以遍历Java中的所有小部件以进行此更改,但这可能会很慢。 我还有什么其他选择?有没有更好的方法来制作具有自定义外

  • 第一次使用JavaFX,所以我对/方法有一个问题。我在做一个弹跳球项目。首先,我使用对象创建球,但由于需要传递更多参数,我决定构建自己的球类()。这是我以前使用时使用的代码: 当将和和放入中时,就会使“球”弹出墙壁。现在,我正试图弄清楚如何使用ball来实现这一点,因为在使用我自己的对象时,无法解析、和方法。如何处理这个/构建自己的等?

  • 我有一个片段,我在其中膨胀“Fragment\u board.xml”: 如您所见,fragment\u board包含一个自定义视图“BoardView”,我想从中加载以下“view\u board.xml”: 我的自定义视图包含两个滚动视图(我使用它进行平移),我希望能够在其他布局中重复使用它。BoardView扩展了外部(垂直)滚动视图,如下所示: 当我独立使用它时,它会膨胀得很好,我可以在

  • 问题内容: 我必须在Android中构建更复杂的自定义视图。最终布局应如下所示: 但是,我只想在XML文件中定义它(不定义SomeView,SomeOtherView等): 这在Android中可行吗?如果可以,那么最干净的方法是什么?我想到的可能解决方案是“重写addView()方法”和“删除所有视图并在以后再次添加它们”,但是我不确定该走哪条路… 在此先感谢您的帮助!:) 问题答案: 绝对有可

  • 我有一个片段,我想在其中使用折叠工具栏布局 当collapsing_toolbar展开时,我希望显示图像,当折叠时,我希望只有@id/custom_layout。custom_layout是一个带有文本视图和图像视图的相对布局。 我想要有完全相同的行为,就像我有以下行为一样: 而不是自定义布局。 为什么这是不工作?即使折叠ToobarLayout扩展我看到的ImageView和自定义布局。 !!注