代码之家  ›  专栏  ›  技术社区  ›  isuPatches

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

  •  0
  • isuPatches  · 技术社区  · 6 年前

    init /抽象基类的构造函数实际上不是最佳实践。我理解这是因为基类初始值设定项发生在 /派生类的构造函数。由于抽象类不是final,因此有一个关于 this 被泄露在 初始化 块

    以下是我想要的:

    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) 
    

    我真的不想在派生类的init中添加任何东西,也不想使 myView 稍后在抽象类中设置的可空/可变变量。

    0 回复  |  直到 6 年前
        1
  •  2
  •   Tenfour04    6 年前

    泄漏 this

    就 LayoutInflator.inflate ,这似乎不是问题,如果只是因为Android的内置视图经常通过 作为 inflate() 方法。例如,DatePicker的构造函数实例化DatePickerSpinnerDelegate,它将该DatePicker实例传递给 充气

    将视图作为父视图传递给 充气 ,通过遵循调用链,我看到父对象发生了两件事。它叫 getContext() 在该父对象上,它调用 addView() 如果 addToRoot 这是真的。所以我认为 这 只要你不超控,它是安全的 执行其他工作,这些工作依赖于您在呼叫后设置的成员 inflate(). But addView() also internally calls and invalidate()`,因此同样的问题也适用于这些。

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

    抑制警告不应意味着忽略警告或只是对代码进行黑客攻击。这意味着,“我确认了失败模式,并检查了我的代码不会以这种方式失败。”如果不是这样,那将是编译器错误,而不是警告。 在Kotlin中,可以使用的抑制注释是 @Suppress("LeakingThis")