Intent, Bundle, SavedStateHandle로 다양한 데이터를 넘겨받는데 특히 객체를 넘겨받을 경우가 많다.
여러가지 방법이 있겠지만 주로 사용하는 방법은 객체를 Json으로 변환한 뒤 다시 받는 쪽에서는 Json을 객체에 매핑시켜 데이터를 가져오는 구조로 주로 사용을 했다.
AS-IS
하지만 이게 매번 하려니 여간 번거로운게 아니다 하나 예시를 보자.
val dataDTO = DataDTO(....)
val intent = Intent(context, InfoActivity::class.java).apply {
val jsonAdapter = moshi.adapter(DataDTO::class.java)
this.putExtra("test", jsonAdapter.toJson(dataDTO))
}
context.startActivity(intent)
데이터를 Json으로 변환하고 다시 객체로 변환하기위에 Moshi를 사용한다면 위와 같은 코드를 사용하게 될 것이다.
그리고 받으려면 마찬가지로 아래와 같이 Json을 다시 객체로 변환하는 과정을 거쳐야 한다.
val dataDTOJson = intent.getStringExtra("test") ?: return
val jsonAdapter = moshi.adapter(DataDTO::class.java)
val dataDTO = jsonAdapter.fromJson(dataDTOJson) ?: return
우선 SIMPLE IS BEST를 사랑하는 나는 단순히 데이터를 넘기는데 너무 복잡하다고 생각이 든다.
단순화 하기위해 유틸성 확장함수를 만들었고 어떻게 사용할수 있나 확인해보자
TO-BE
보내는 부분 (강화 +1)
val dataDTO = DataDTO(....)
val intent = Intent(context, InfoActivity::class.java).apply {
putAsJson("test", dataDTO)
}
어떤가? 여기서 한번더 단순화 해보면 다음과 같이 사용할 수 있다.
보내는 부분 (강화 +2)
val dataDTO = DataDTO(....)
context.start<InfoActivity> {
putAsJson("test", dataDTO)
}
받을때
val dataDTO = intent.getAsObject<DataDTO>("test")
어떻게 했나?
위처럼 단순화하기 위해 생성한 확장 함수는 다음과 같다.
Intent, Bundle, SavedStateHandle 모두 커버가능하며 정말 단순화하여 객체를 전달 할 수 있다. Gson 사용을 선호하는 분이라면 MoshiProvider 부분만 Gson으로 적절히 변경해서 사용하면 되겠다.
import android.content.Intent
import android.os.Bundle
import androidx.lifecycle.SavedStateHandle
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
object MoshiProvider {
val instance: Moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
}
// Bundle에 객체를 JSON으로 직렬화하여 저장합니다.
inline fun <reified T> Bundle.putAsJson(key: String, value: T) {
val jsonAdapter = MoshiProvider.instance.adapter(T::class.java)
this.putString(key, jsonAdapter.toJson(value))
}
// Bundle에서 JSON 문자열을 객체로 역직렬화하여 가져옵니다.
inline fun <reified T> Bundle.getAsObject(key: String): T? {
val json = this.getString(key) ?: return null
val jsonAdapter = MoshiProvider.instance.adapter(T::class.java)
return jsonAdapter.fromJson(json)
}
// Intent에 객체를 JSON으로 직렬화하여 저장합니다.
inline fun <reified T> Intent.putAsJson(key: String, value: T) {
val jsonAdapter = MoshiProvider.instance.adapter(T::class.java)
this.putExtra(key, jsonAdapter.toJson(value))
}
// Intent에서 JSON 문자열을 객체로 역직렬화하여 가져옵니다.
inline fun <reified T> Intent.getAsObject(key: String): T? {
val json = this.getStringExtra(key) ?: return null
val jsonAdapter = MoshiProvider.instance.adapter(T::class.java)
return jsonAdapter.fromJson(json)
}
// SavedStateHandle에 객체를 JSON으로 직렬화하여 저장합니다.
inline fun <reified T> SavedStateHandle.putAsJson(key: String, value: T) {
val jsonAdapter = MoshiProvider.instance.adapter(T::class.java)
this[key] = jsonAdapter.toJson(value)
}
// SavedStateHandle에서 JSON 문자열을 객체로 역직렬화하여 가져옵니다.
inline fun <reified T> SavedStateHandle.getAsObject(key: String): T? {
val json = this.get<String>(key)
val jsonAdapter = MoshiProvider.instance.adapter(T::class.java)
return json?.let { jsonAdapter.fromJson(it) }
}
그리고 추가로 Intent를 단순하게 사용하려면 아래 확장함수를 사용하면 된다.
Context, Fragment, Activity만 가지고 있다면 손쉽게 startActivity를 할 수 있다.
inline fun <reified A : Activity> Context.start(configIntent: Intent.() -> Unit = {}) {
startActivity(Intent(this, A::class.java).apply(configIntent))
}
inline fun <reified A : Activity> Activity.start(configIntent: Intent.() -> Unit = {}) {
startActivity(Intent(this, A::class.java).apply(configIntent))
}
inline fun <reified A : Activity> Fragment.start(configIntent: Intent.() -> Unit = {}) {
startActivity(Intent(this.context, A::class.java).apply(configIntent))
}
복잡한건 심플하게, 최대한 단순하게 사용해보자.
'개발 공부 기록하기 > - Android' 카테고리의 다른 글
Android Kotlin EditText 콤마 붙히기 (feat. Extension) (0) | 2021.09.05 |
---|---|
Android Flavor + Fastlane (Release + Screenshot) 자동화하기 (2) | 2021.07.22 |
Android Virtual Device 하단 버튼 제거 (0) | 2021.07.21 |
안드로이드 - 배경 투명도 조절하기 (0) | 2021.06.15 |
FCM Push Notification(HTTP v1) with OAuth 2.0 Playground / Postman / Terminal - Part2 (9) | 2021.01.19 |