Fragment间优雅地处理参数

303 阅读1分钟

juejin.cn/post/718472… 文章分析了如何在Activity间优雅地处理参数问题,其实Fragmnet也是类似,就不多做解释直接上代码吧。

  • 扩展函数+属性委托传参
  1. 扩展函数,key value方式设置参数

给Fragment增加扩展函数set,operator是重载运算符,以下代码定义: 给Fragment增加扩展函数set,且重载它的运算符。

//定义
inline operator fun <reified T> Fragment.set(key: String, value: T) {
    val bundle = this.arguments ?: Bundle()//注意Bundle的复用
    this.arguments = bundle.apply {
        when (value) {
            is Int -> {
                this.putInt(key, value)
            }
            is String -> {
                this.putString(key, value)
            }
            is Float -> {
                this.putFloat(key, value)
            }
            is Double -> {
                this.putDouble(key, value)
            }
            is Boolean -> {
                this.putBoolean(key, value)
            }
            is Long -> {
                this.putLong(key, value)
            }
            is String -> {
                this.putString(key, value)
            }
            is Parcelable -> {
                this.putParcelable(key, value)
            }
            is ArrayList<*> -> {
                this.putParcelableArrayList(key, value as ArrayList<Parcelable>)
            }
        }
    }
}

//调用

class VideoListFragment : BaseFragment(R.layout.fragment_video_list) {

    companion object {

        fun getInstance(type: String, category: Int): VideoListFragment {
            return VideoListFragment().apply {
                this["type"] = type
                this["category"] = category
            }
        }
    }

注意:因为是给Fragment定义了扩展函数(内部实现了Bundle的构建),所以只需要给Fragment这是参数即可。

  1. Kotlin委托方式获取值

//定义,其实跟Activity.intents类似 
inline fun <reified T : Any> Fragment.intents(): IntentsProperty<Any, T> {
    return IntentsProperty{
        this.arguments
    }
}

class IntentsProperty<in A : Any, out T : Any>(private val f:(()->Bundle?)) :
    ReadOnlyProperty<A, T> {

    private var value: T? = null

    override operator fun getValue(thisRef: A, property: KProperty<*>): T {
        value?.let { return it }
        val name = property.name

        return ((f.invoke()?.get(name)) as T).let {
            value = it
            it
        }
    }
}

//调用
private val type: String by intents()

private val category: Int by intents()