Kotlin扩展功能 - 如何使其全球化?

时间:2018-01-09 04:11:38

标签: android kotlin kotlin-extension

我在Android ViewGroup类上创建了一个Kotlin扩展函数,以便它可以更轻松地进行布局通胀调用。所以,这是我的扩展名:

fun ViewGroup.inflate(layoutRes: Int): View {
    return LayoutInflater.from(context).inflate(layoutRes, this, false)
}

然后我可以在适配器类中使用它来膨胀布局:

 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val v = parent.inflate(R.layout.view_item)
    return ViewHolder(v)
}

我已在我用于RecyclerView的适配器类中声明了此扩展,以便它可以使通胀调用更容易。但我想要所有适配器或我应该说所有ViewGroup类来查看此扩展。我希望它永久化。

它似乎只是在我声明不是全局的地方。我应该在哪里声明此扩展名,以便在我使用视图组的任何时候都可以使用此方法扩展名?

3 个答案:

答案 0 :(得分:3)

<强>问题:

如果你在这里定义扩展函数(1),它将是全局可访问的,但这是不好的样式,因为这是(特殊适配器)MyArrayAdapter的类文件,而inflate意味着在整个项目范围内使用。

如果你在这里定义扩展函数(2),它只能在MyArrayAdapter的上下文中访问。

// (1)
class MyArrayAdapter: ArrayAdapter<String> {
   // (2)
}

我会做什么:

使用仅作为实用程序的顶级声明创建文件 Util.kt

这就是 Util.kt 文件的样子:

package com.yourpackagepath // package in which Utils.kt resides

// written with expression body, which makes it more concise
fun ViewGroup.inflate(layoutRes: Int) = LayoutInflater.from(getContext()).inflate(layoutRes, this, false)

这种扩展在项目范围内可用,并且它是一种很好的样式,因为 Util.kt 意味着全局实用程序可以在任何地方使用。

你会这样称呼:

val v = parent.inflate(R.layout.view_item)

如果您不在同一个包中使用它,请按以下方式导入:

import com.yourpackagepath.inflate

答案 1 :(得分:2)

您可以通过在对象类中进行声明来使扩展功能成为全局功能,如下所示:

object ViewExtension{

 fun Spinner.validate(): Boolean  {
    if(!this.isSelected){
        this.setSpinnerHint(this.context.getString(R.string.please_select))
        return false
    }
    return true
 }

 fun TextInputLayout.validate(): Boolean{
    if(TextUtils.isEmpty(editText?.text)){
        this.error =  this.context.getString(R.string.required)
        return false
    }
    return true
 }
}

如何使用扩展功能

fun validateFields(): Boolean{
    var allSelected = true

    textInput.validate().apply {
        if(!this)
            allSelected = false
    }
    
    spinner.validate().apply {
        if(!this)
            allSelected = false
    }

 }

此外,我们需要在使用任何类之前导入validate方法:

import com.example.ViewExtension.validate

答案 2 :(得分:1)

  

我已在适配器类中声明了此扩展,我正在使用它进行回收查看,以便它可以使通胀调用更容易。

像这样,它只能在适配器类的上下文中使用。

在包级别声明它(顶级)或考虑定义包含扩展名的对象:

object ViewGroupExt {
    //extensions go here
}

现在在调用者方面,您需要将ViewGroupExt纳入范围:

with(ViewGroupExt){
   //call extensions
}

与包级声明相比,这具有必须使其显式的访问权限。