본문 바로가기
개발/안드로이드

(Android) bundleOf로 데이터 편하게 전달하기

by DinoDev 2025. 5. 9.
728x90
반응형

이번 포스팅은 bundleOf()를 사용해서 Activity나 Fragment에 데이터를 더욱 더 쉽게 전달하는 방법에 대해 소개 합니다.

Setup

bundleOf()함수는 Android KTX중에 core-ktx에 있는 함수 입니다.
그래서 사용하기 전에 build.gradle에 core-ktx를 추가해 줘야 합니다.
이 포스팅을 작성했을 때 버전은 1.2.0 입니다.

dependencies {
    implementation "androidx.core:core-ktx:1.15.0"
}

bundleOf()

bundleOf 함수는 key와 value가 쌍으로 이루어진 요소를 담고 있는 Bundle을 만들어서 리턴하는 함수 입니다.

함수는 Pair<String, Any?>를 파라미터로 전달 받고 Bundle을 리턴하는 형태로 되어 있습니다. 또한 vararg이기 때문에 , 로 구분해서 여러 Pair를 전달 할 수 있습니다.

// Sample enum class
@Parcelize
enum class AndroidLanguage : Parcelable {
    Java,
    Kotlin
}

val bundle: Bundle = bundleOf(
    "key1" to 5,
    "key2" to 2.4f,
    "key3" to "Hello World",
    "key4" to AndroidLanguage.Kotlin
)

bundleOf() 함수는 내부에서 다양한 Type을 지원하기 때문에 Type Casting을 직접 해서 넣어 줄 필요가 없습니다. 또한 Type 검사에 대한 우선순위를 가지고 있기 때문에 Parcelable/Serializable 두개의 타입을 동시에 가지고 있는 Class도 Parcelable로 전달 할 수 있습니다.

fun bundleOf(vararg pairs: Pair<String, Any?>) = Bundle(pairs.size).apply {
    for ((key, value) in pairs) {
        when (value) {
            null -> putString(key, null) // Any nullable type will suffice.

            // Scalars
            is Boolean -> putBoolean(key, value)
            is Byte -> putByte(key, value)
            is Char -> putChar(key, value)
            is Double -> putDouble(key, value)
            is Float -> putFloat(key, value)
            is Int -> putInt(key, value)
            is Long -> putLong(key, value)
            is Short -> putShort(key, value)

            // References
            is Bundle -> putBundle(key, value)
            is CharSequence -> putCharSequence(key, value)
            is Parcelable -> putParcelable(key, value)

            // Scalar arrays
            is BooleanArray -> putBooleanArray(key, value)
            is ByteArray -> putByteArray(key, value)
            is CharArray -> putCharArray(key, value)
            is DoubleArray -> putDoubleArray(key, value)
            is FloatArray -> putFloatArray(key, value)
            is IntArray -> putIntArray(key, value)
            is LongArray -> putLongArray(key, value)
            is ShortArray -> putShortArray(key, value)

            // Reference arrays
            is Array<*> -> {
                val componentType = value::class.java.componentType
                @Suppress("UNCHECKED_CAST") // Checked by reflection.
                when {
                    Parcelable::class.java.isAssignableFrom(componentType) -> {
                        putParcelableArray(key, value as Array<Parcelable>)
                    }
                    String::class.java.isAssignableFrom(componentType) -> {
                        putStringArray(key, value as Array<String>)
                    }
                    CharSequence::class.java.isAssignableFrom(componentType) -> {
                        putCharSequenceArray(key, value as Array<CharSequence>)
                    }
                    Serializable::class.java.isAssignableFrom(componentType) -> {
                        putSerializable(key, value)
                    }
                    else -> {
                        val valueType = componentType.canonicalName
                        throw IllegalArgumentException(
                            "Illegal value array type $valueType for key \"$key\"")
                    }
                }
            }

            // Last resort. Also we must check this after Array<*> as all arrays are serializable.
            is Serializable -> putSerializable(key, value)

            else -> {
                if (Build.VERSION.SDK_INT >= 18 && value is Binder) {
                    putBinder(key, value)
                } else if (Build.VERSION.SDK_INT >= 21 && value is Size) {
                    putSize(key, value)
                } else if (Build.VERSION.SDK_INT >= 21 && value is SizeF) {
                    putSizeF(key, value)
                } else {
                    val valueType = value.javaClass.canonicalName
                    throw IllegalArgumentException("Illegal value type $valueType for key \"$key\"")
                }
            }
        }
    }
}

기존 방식과 비교

기존에 Activity끼리 데이터를 주고 받을 때는 Intent에 putExtra로 key와 value를 넣어주는 방식을 사용 했습니다.

val intent = Intent(this, MainActivity::class.java)
intent.putExtra("key1", 5)
intent.putExtra("key2", 2.4f)
intent.putExtra("key3", "Hello World")
intent.putExtra("key4", AndroidLanguage.Kotlin)

하지만 위 처럼 넣게 되면 AndroidLanguage가 Parcelable이면서 Serializable이기 때문에 함수 Overload 에러가 발생하게 됩니다.

그래서 enum class를 전달 할 땐 AndroidLanguage.Kotlin as Parcelable 이렇게 type casting을 해줘야 합니다.

Activity

bundleOf()를 사용하게 된다면 더 깔끔하게 작성 할 수 있습니다.

val intent = Intent(this, MainActivity::class.java)
val bundle = bundleOf(
    "key1" to 5,
    "key2" to 2.4f,
    "key3" to "Hello World",
    "key4" to AndroidLanguage.Kotlin
)
intent.putExtras(bundle)

위 코드에서는 key4에 넣는 enum class에서 에러가 발생하지 않습니다.
그리고 bundleOf() 내부 구현을 보면 Serializable보다 Parcelable이 우선순위가 높기 때문에 Serializable로 들어갈 걱정을 하지 않아도 됩니다.

intent에 bundle을 넣을 때는 뒤에 s가 있는 putExtras 함수를 사용하면 됩니다.

Fragment

fragment도 동일하게 bundle을 만들고 fragment에 arguments에 bundle을 넣어주면 됩니다.

val fragment = MainFragment()
val bundle = bundleOf(
    "key1" to 5,
    "key2" to 2.4f,
    "key3" to "Hello World",
    "key4" to AndroidLanguage.Kotlin
)
fragment.arguments = bundle

마무리

bundleOf()함수를 사용하면 코드를 더욱 간결하게 작성해서 가독성이 높게 만들 수 있으며 Type에 대한 걱정을 하지 않아도 되서 코드를 작성 할 때 걱정을 덜어줄 수 있습니다.

 


블로그 글에 대해 궁금한 점이 있다면 아래 카카오톡 오픈채팅에 들어와서 질문해주세요

 

Android Kotlin Compose QnA

 

open.kakao.com

 

728x90
반응형