이번 포스팅은 Activity를 start하거나 Fragment를 보여주는 코드를 어떻게 하면 간단하게 보여줄 수 있는지 소개하고자 합니다.

Activity

기존 스타일

// in Activity
val intent = Intent(this, DestinationActivity::class.java)
intent.putExtra("key1", "value1")
intent.putExtra("key2", "value2")
startActivity(intent)

// in Fragment
val intent = Intent(requireContext(), DestinationActivity::class.java)
intent.putExtra("key1", "value1")
intent.putExtra("key2", "value2")
startActivity(intent)

Companion

ActivityTemplate.kt

abstract class ActivityTemplate<T : Activity> {

    private val clazz: Class<*>
        get() = ((this.javaClass.genericSuperclass as ParameterizedType?)?.actualTypeArguments
            ?.get(0) as Class<*>)

    fun start(
        context: Context,
        vararg param: Pair<String, Any?>,
        intentAction: Intent.() -> Unit = {}
    ) {
        context.startActivity(createIntent(context, *param).apply(intentAction))
    }

    fun createIntent(context: Context, vararg param: Pair<String, Any?>) =
        Intent(context, clazz).apply { putExtras(bundleOf(*param)) }

}

DestinationActivity.kt

class DestinationActivity : AppCompatActivity(R.layout.activity_destination) {
    companion object : ActivityTemplate<DestinationActivity>()
}

사용하기

// in Activity
DestinationActivity.start(this, "key1" to "value1", "key2" to "value2")

// in Fragment
DestinationActivity.start(requireContext(), "key1" to "value1", "key2" to "value2")

기존 스타일보다 사용하기는 편해졌지만 Activity마다 companion object를 만들고 ActivityTemplate을 상속해야 하는 작은 불편함이 있습니다.

Extension function

IntentExtension.kt

fun <T> createIntent(
    context: Context,
    clazz: Class<out T>,
    params: Array<out Pair<String, Any?>>
) = Intent(context, clazz).apply { putExtras(bundleOf(*params)) }

ContextExtension.kt

inline fun <reified T : Activity> Context.startActivity(
    vararg param: Pair<String, Any?>,
    intentAction: Intent.() -> Unit = {}
) {
    val intent = createIntent(this, T::class.java, param).apply(intentAction)
    startActivity(intent)
}

FragmentExtension.kt

inline fun <reified T : Activity> Fragment.startActivity(
    vararg param: Pair<String, Any?>,
    intentAction: Intent.() -> Unit = {}
) {
    val intent = createIntent(requireContext(), T::class.java, param).apply(intentAction)
    startActivity(intent)
}