使用kotlin来启动Android Activity

in 默认分类 with 0 comment

在Android开发中,我们经常有启动一个新的Activity的需求。通常,我们都是通过直接调用Intent(Context packageContext, Class<?> cls)方法构造一个Intent,然后再调用Activity类中的startActivity方法来启用新的Activity,但是,我们有办法使用Kotlin来让这一切变得更简单吗,答案当然是肯定的。

我们知道,在kotlin中我们可以使用inline关键字来创建 一个内联函数,而内联函数有一个很重要的特性就是还可以使用reified来标记一个实化类型参数,这样我们就可以不用传递一个Class引用了,直接传入类型实参即可。另外,由于我们可以一般都是通过Activity来启动一个新的Activity,所以我们可以为Activity创建一个扩展函数,具体代码如下:

inline fun <reified T : Activity> Activity.startActivity() {
    val intent = Intent(this, T::class.java)
    startActivity(intent)
}

通过使用这个扩展函数,我们启动一个新的Activity就变得简单多了,在一个Activity中调用以下代码即可启动SecondActiivty:

startActivity<SecondActivity>()  //没错,只需要这一行代码

但是,上面的代码还存在一些问题,如果我们需要向新启动的Activityl中传递一些参数怎么办?通过上面的方式我们就没办法去操作创建目标Intent了啊。

为了解决这个问题,我们可以对上述扩展函数稍加改进,改进过的函数添加了一个带接收者的lambda表达式:

inline fun <reified T : Activity> Activity.startActivity(intentAction: Intent.() -> Unit = {}) {
    val intent = Intent(this, T::class.java)
    intent.intentAction()
    startActivity(intent)
}

注意到上面的代码我为接收者为Intent的lambda表达式设置了一个默认的空的lambda表达式,这样当我们不需要传递参数时,依然可以像之前一样使用一行代码即可启动一个新的Actiivty。当我们需要传递参数给新的Activity时,我们可以通过传入一个lambda表达式来操作内部创建的Intent:

class ParamsActivity : AppCompatActivity() {

    companion object{
        private const val EXTRA_KEY_TEXT="ParamsActivity.extra.text"

        fun startActivity(activity:Activity,text:String){
            activity.startActivity<ParamsActivity> {
                putExtra(EXTRA_KEY_TEXT,text)
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_params)

        text_view.text=intent.getStringExtra(EXTRA_KEY_TEXT)
    }
}

上述伴生对象方法 startActivity(activity:Activity,text:String) 即实现了为启动ParamsActivity的Intent添加一个类型为String的extra内容的功能。

事实上,受制于java的泛型实现,不少地方的函数调用我们都需要传递一个Class实例来传入类型。依靠kotlin的实化类型参数,在不少地方,我们都可以通过类泛型的方式来传入类型,从而免去了Class实例的传入,使代码看起来更简洁,也更具有可读性,推荐大家在合适的地方积极使用实化类型参数来代替Class类型的形参。