在Kotlin中创建BaseView类

时间:2019-02-18 08:41:51

标签: android kotlin

我正在Kotlin中创建BaseView类,所有子视图都将扩展。

我的问题是膨胀了BaseView类中的Layout,因为为BaseView构造函数提供的布局资源ID太晚了。

这是我的BaseView

 abstract class BaseView @JvmOverloads constructor(
    context: Context?,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0
) : MaterialCardView(context, attributeSet, defStyleAttr) {

    protected abstract val viewResourceId: Int
    protected abstract val needsRefresh: Boolean

    init {

        View.inflate(context,viewResourceId, this) // viewResourceId is not initialized here as yet
    }


    enum class State {
        DISABLED,
        LOADING,
        DONE,
        FAILED
    }
}

问题是众所周知的“在构造函数中访问非最终属性”。以前,我在Java中应用了完全相同的策略,并且这种方法一直有效。

我将如何处理这种情况? 。我需要在基础上增加布局。这样做是有道理的,因为通货膨胀是一种常见的操作。

委托财产是走的路吗?

编辑:这是我的客户的样子

class StudentView @JvmOverloads constructor(
    context: Context?,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0
) : BaseRegion(context, attributeSet, defStyleAttr) {
    override val viewResourceId=R.layout.student_view
    override val needsRefresh=false

    init {
        context?.
            let {  setCardBackgroundColor(ContextCompat.getColorStateList(context,R.color.colorAccent)!!)}

    }
}

1 个答案:

答案 0 :(得分:1)

当您使用带有后备字段的属性时,这将不起作用,因为该字段的初始化发生在子类的构造函数中,该子类在父类的构造函数之后运行。

但是,您可以使用计算属性,该属性将在父级调用它时按预期进行评估:

override val viewResourceId: Int
    get() = R.layout.some_layout

或者您可以定义一个抽象函数,并将其重写,这基本上是同一件事:

override fun getViewResourceId(): Int = R.layout.some_layout

另一方面,在某些自定义视图中使用@JvmOverloads可能是一个问题,因为调用为您自己的类生成的任何构造函数都将首先委托给该类中的all-params构造函数,然后再调用super的all-params构造函数,而不是每个构造函数都使用匹配数量的参数调用super方法。有关详情,请参见this article