본문 바로가기

Android + Kotlin

[Android Kotlin] Fragment arguments 를 쾌적하게(Extension) 해보자.

반응형

Fragment 사용시 데이터 전달은 arguments 를 이용합니다.

arguments는 Bundle 데이터를 사용하기에 데이터를 가져오는 코드를 구현해야 합니다.

단순하고 반복적인 코드들이 파라미터 개수에 따라 코드량이 늘어나게 되어, 가독성이 조금이나마 떨어지기에 개션을 해보고자 합니다.

 

이전 intent 데이터를 개선한 것과 동일한 방법으로 구현하였습니다.

 

 

[Android Kotlin] 화면간 intent 사용을 쾌적하게(Extension) 해보자.

안드로이드는 intent를 이용하여 화면간 데이터를 전달합니다. 이렇게 자주 사용하는 intent인데, 오랜만에 특정 화면을 호출할때면 어떤 데이터를 어떤 키로 보내면 되는지.. intent를 받는 화면은

heeeju4lov.tistory.com

 


 

 

일반적으로 Fragment 에서 arguments를 사용하는 경우, 아래 코드와 같이 데이터를 가져옵니다.

 

/**
 * 일반적인 fragment arguments data get 방법
 */
arguments?.getString(INTENT_EXTRA_KEY_TEXT)?.let {
    println("text is $it")
}
arguments?.getInt(INTENT_EXTRA_KEY_NUMBER)?.let {
    println("number is $it")
}
arguments?.getBoolean(INTENT_EXTRA_KEY_IS_OK)?.let {
    println("isOK is $it")
}
arguments?.getSerializable(INTENT_EXTRA_KEY_DATA)?.let {
    println("isOK is ${it as IntentData}")
}

 

단순하고 중복된 코드로  보기만해도 숨이 턱~ 막히는 느낌입니다.

 

이를 좀더 쾌적하게 수정하고자 했습니다.

 


 

 

Fragment Extension으로 변수 사용시 자동으로 가져오도록 하였습니다.

 

inline fun<reified T: Any> Fragment.argumentParams(key: String, defaultValue: T) = lazy {
    val result = when(defaultValue) {
        is Boolean -> arguments?.getBoolean(key, defaultValue)
        is Int -> arguments?.getInt(key, defaultValue)
        is CharSequence -> arguments?.getString(key)
        is Serializable -> arguments?.getSerializable(key) ?: defaultValue
        else -> throw IllegalArgumentException("IllegalArgument value type [${defaultValue.javaClass}] / key [$key]")
    } as? T
    return@lazy result ?: defaultValue
}


inline fun<reified T: Any> Fragment.argumentParams(key: String, crossinline defaultValue: () -> T? = { null }) = lazy {
    val objectType = T::class.javaObjectType
    val result = when {
        Serializable::class.java.isAssignableFrom(objectType) -> arguments?.getSerializable(key) ?: defaultValue.invoke()
        else -> throw IllegalArgumentException("Illegal value type [${objectType}] / key [$key]")
    } as? T
    return@lazy result
}

inline fun<reified T: Any> Fragment.argumentParamsNotNull(key: String) = lazy<T> {
    val objectType = T::class.javaObjectType
    val result = when {
        Serializable::class.java.isAssignableFrom(objectType) -> arguments?.getSerializable(key)
        else -> throw IllegalArgumentException("Illegal value type [${objectType}] / key [$key]")
    } as T
    return@lazy result
}

 

사용 방법은 변수 선언하는 부분에 데이터가 셋팅되도록 구현하면 됩니다.

 

private val text: String? by argumentParams(INTENT_EXTRA_KEY_TEXT)
private val number: Int? by argumentParams(INTENT_EXTRA_KEY_NUMBER, -1)
private val isOk: Boolean? by argumentParams(INTENT_EXTRA_KEY_IS_OK, false)
private val data: IntentData? by argumentParams(INTENT_EXTRA_KEY_DATA)

 

위의 코드는 해당 변수(text, number, ...) 를 사용시 자동으로 arguments에서 데이터를 가져오도록 구현되었습니다.

Extension으로 구현된 만큼, 모든 Fragment 클래스에서 사용 가능합니다.

 


 

 

결과는 아래와 같이 일반적인 방법과 동일한 결과를 보실수 있으십니다.

 

 

 

 

전체 소스 코드는 아래 Github 링크를 확인해 주세요.

 

GitHub - rcbuilders/RemindSampleApp: https://heeeju4lov.tistory.com/ 블로그에서 Android + Kotlin 강좌에서 사용함.

https://heeeju4lov.tistory.com/ 블로그에서 Android + Kotlin 강좌에서 사용함. - GitHub - rcbuilders/RemindSampleApp: https://heeeju4lov.tistory.com/ 블로그에서 Android + Kotlin 강좌에서 사용함.

github.com

 

 

위의 코드 구현시에 사용된 inline, crossinline, reified, 제네릭 타입<T> 에 대해서는 아래 게시물 링크를 확인하시면 도움이 되실거예요.

 

[Android Kotlin] inline 함수 어떤 경우에 사용하나요?

inline 함수는 어떨때 사용해야 할까요? 알고나면 쉽지만, 막상 사용하려면 어디에 사용해야할지 잘 모르는게 inline 함수 있것 같습니다. (사실, 저도 막~ 잘 알아서 여기저기 사용을 하지는.. 못합

heeeju4lov.tistory.com

 

[Android Kotlin] crossinline, reified 를 알아보자.

지난 inline, noinline 게시글에 이어 crossinline, reified 에 대해 알아보겠습니다. inline, noinline 에 대해서는 아래 링크를 확인해 주세요. [Android Kotlin] inline 함수 어떤 경우에 사용하나요? inline..

heeeju4lov.tistory.com

 

[Android Kotlin] <T>, <K, V> , <*> 너희 정체가 뭐니?

구글링을 하거나, 라이브러리의 소스 등을 보면 , , <*> 이런 코드들이 보입니다. 도대체 뭘까요? 이번 게시물에서는 이 코드들에 대해서 알아보고, 예제를 통해 사용법을 익히고, 친해져보도록

heeeju4lov.tistory.com

 

반응형