优雅读取Activity的Intent、Fragment的Argument

2,595 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

本篇文章将从属性委托的角度来实现Activity的Intent、Fragment的Argument优雅读写的封装

属性委托实现方式有两种,这里直接通过实现接口的形式实现:

  • var修饰的属性实现属性委托需要实现ReadWriteProperty接口
  • val修饰的属性实现属性委托需要实现ReadOnlyProperty接口

这里由于我们只需要读取值,所以直接实现ReadOnlyProperty接口即可。下面直接上Activity的Intent委托读取代码 :

class IntentWrapper<T>(private val default: T) : ReadOnlyProperty<AppCompatActivity, T?> {
    override fun getValue(thisRef: AppCompatActivity, property: KProperty<*>): T? {
        return  when(default) {
            is Int -> thisRef.intent.getIntExtra(property.name, default)
            is String -> thisRef.intent.getStringExtra(property.name)
            else -> throw  Exception()
        } as? T
    }
}

需要注意,在这里读取Activity的Intent使用的key默认为属性名称:property.name,这也就意味着通过Intent存储值的时候key也要使用属性名称。

如果需要读写Intent的话key不想要使用属性名称,那就得对这个属性委托类IntentWrapper稍微改造下,构造方法中支持从外部传入key键值

上面的属性委托类IntentWrapper中,只是简单处理了StringInt类型,其他的类型BooleanFloat等类型需要请自行添加。

看下使用:

private val data by IntentWrapper(56)

//读
printlin(data)

上面使用起来还是有一丢丢不优雅,每次都得手动创建IntentWrapper并传入默认值,我们可以封装几个常用类型的方法,实现起来更加方便:

fun intIntent(default: Int = 0) = IntentWrapper(default)

fun stringIntent(default: String = "") = IntentWrapper(default)

intIntent()方法给了一个默认值为0,外部可以选择性传入的默认值,其他的类型也是一样处理。

然后就可以这样使用:

private val data by intIntent()

上面主要展示的是读取Activity的Intent,Fragment的Argument处理类似:

class ArgumentWrapper<T>(private val default: T) : ReadOnlyProperty<Fragment, T?> {
    override fun getValue(thisRef: Fragment, property: KProperty<*>): T? {
        return when(default) {
            is Int -> thisRef.arguments?.getInt(property.name, default)
            is String -> thisRef.arguments?.getString(property.name)
            else -> throw Exception()
        } as? T
    }
}

使用起来也和Activity类似,这里就不做展示了。当然了,这里可以定义几个常用类型的方法创建ArgumentWrapper,参考上面Activity的处理即可。

后续准备出一篇文章,从类委托的角度考虑封装下Activity的Intent、Fragment的Argument的读取。