흔히 Activity와 Fragment 간에 데이터를 전달할 때 우리는 Intent
와 Bundle
을 사용해서 데이터를 전달합니다. 하지만 두 개의 용도는 명확히 다릅니다.
Intent
는 저장이 아닌 전달하는 수단으로의 객체이고 Bundle
은 상태/값 등을 저장하기 위한 객체입니다. Bundle
은 Map의 형태로 되어있습니다.
Intent
에서 데이터를 전달할 때 다음과 같은 두 가지 코드를 보셨을 겁니다.
val intent = Intent()
intent.putExtra("key","value")
val intent = Intent()
val bundle =Bundle()
bundle.putString("key","value")
intent.putExtra("bundle",bundle)
위의 두 코드의 결과는 같습니다. 하나는 Intent
내부의 putExtra() 함수를 통해 value를 넘겨주는 것이고 하나는 Bundle
을 만들고 그 안에 데이터를 넣어서 Intent
를 통해 전달을 해줍니다. 두 개의 차이는 무엇이 있을까요?
Intent
의 내부 함수를 보면 보시다시피 Bundle을 통해 데이터를 전달하고 있습니다.
public @NonNull Intent putExtra(String name, @Nullable String value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putString(name, value);
return this;
}
Bundle
은 내부적으로 Map을 활용해 바로 데이터를 넣어주고 있습니다.
ArrayMap<String, Object> mMap = null;
public void putString(@Nullable String key, @Nullable String value) {
unparcel();
mMap.put(key, value);
}
차이점은 보면 결국에는 Bundle
을 통해 보내주지 않고 Intent
내부 함수를 사용하면 내부적으로 Bundle
을 생성해서 보내줍니다. 비용적인 측면에서 보았을 때는 후자가 나을 것 같지만 가독성이나 코드 길이 면에서는 전자가 나을 수 있겠다는 생각이 들었습니다.
추가적으로, 그렇다면 객체를 전달하고 싶다면 어떻게 해야 할까요? 일단 객체를 프로세스 간 전달하기 위해서는 직렬화 과정을 거쳐야 하기 때문에 Serializable
이나 Parcelable
을 구현한 클래스를 통해 보내주어야 합니다. (일반적으로 Paraceable은 리플렉션 과정이 없기 때문에 Serializable 보다 10배 빠르다고 합니다. 참고 - Parcelable vs Serializable)
✅ Serializable를 통해 객체 전달하기
data class SimpleData(
val name : String
) : Serializable
그리고 MainActivity에서 다음과 같이 전달을 해주면
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent= Intent(this, MainActivity2::class.java)
val bundle = Bundle()
bundle.putSerializable("key", SimpleData(name = "hi"))
intent.apply {
this.putExtra("bundle", bundle)
}
startActivity(intent)
}
}
MainActivity2에서 다음과 같이 받아서 쓸 수 있습니다.
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
val bundle = intent.getBundleExtra("bundle")
val simpleData = bundle?.getSerializable("key") as SimpleData
}
}
✅ Parcelable을 통해 객체 전달하기
사용하기 위해 Module 수준에서 plugin을 추가해야 합니다. (Project 수준 X)
plugins {
id 'kotlin-parcelize'
}
그리고 데이터 클래스를 다음과 같이 구현해줍니다.
@Parcelize
data class SimpleData(
val name : String
) : Parcelable
그리고 MainActivity에서 다음과 같이 전달을 해주면
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent= Intent(this, MainActivity2::class.java)
val bundle = Bundle()
bundle.putParcelable("key", SimpleData(name = "hi"))
intent.apply {
this.putExtra("bundle", bundle)
}
startActivity(intent)
}
}
MainActivity2에서 다음과 같이 받아서 쓸 수 있습니다.
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
val bundle = intent.getBundleExtra("bundle")
val name = bundle?.getParcelable<SimpleData>("key")?.name
}
}
정리하자면 다음과 같습니다.
- Intent는 데이터를 전달하는 수단으로의 객체이고 Bundle은 상태나/값을 저장하기 위한 Map형태로 된 객체이다.
- bundle을 통해 객체를 전달하고 싶을 때는 직렬화과정이 필요하기에
Serializable
이나Parcelable
를 사용한다.
'개발 > Android' 카테고리의 다른 글
[Android] LiveData에 대해 알아보자 (0) | 2022.05.10 |
---|---|
[Android] ViewModel Factory에 관하여 (1) | 2022.05.04 |
[Android] ACC ViewModel이란? - 정의, 사용법, 주의할점 (0) | 2022.04.16 |
[Android] 라이브러리 없이 ImageView에 URL 이미지 표시하기 (0) | 2022.04.08 |
[Android] Adapter에서 ViewModel 사용하기 (0) | 2022.03.30 |
댓글