반응형
Intent를 통해 객체 전달
- 객체 전달시 객체 직렬화 필요 -> 객체가 갖고 있는 다양한 변수들을 하나의 Byte 별 형태로 만드는 작업 (*객체의 주소값을 넘기게 되면 프로세스 간에 의존성이 생겨 위험할 수 있다! 그래서 반드시 직렬화를 통해 값을 넘겨 이동한 액티비티에서 새로 객체를 만들어줘야 함)
- Parcelabel 인터페이스를 사용해 작업
- 클래스를 가지고 객체를 만들면 객체들은 같은 구조를(변수와 메서드) 갖게 되고, 오직 변수 안에 담겨진 값만 달라짐
- 변수가 갖는 값들을 추출해 Parcel이라는 객체에 저장하고 intent에 담음
- 다른 액티비티가 실행될 때 Parcel이 담겨져 있는 intent가 전달이 되고 이를 추출해 새로운 액티비티 실행에 사용
- 새로 실행된 액티비티에서 TestClass 객체를 만든 후 intent를 통해 전달 받은 Parcel 객체에 들어있는 변수의 값들을 추출해 다시 셋팅 * 실제로는 객체가 전달되는데 아니라 객체 안의 데이터만 Parcel 객체를 통해 전달되고, 액티비티 이동 후 객체 인스턴스를 다시 만들어 Parcel 에서 데이터만 추출해 셋팅해 사용하는 방식
[MainActivity.kt]
binding.button.setOnClickListener {
val second_intent = Intent(this, SecondActivity::class.java)
val t1 = TestClass()
t1.data1 = 100
t1.data2 = "문자열1"
second_intent.putExtra("obj1",t1) // percelable 인터페이스를 구현한 객체를 셋팅
// intent 객체를 전달해 새로운 액티비티를 실행시킴
activityResultLauncher.launch(second_intent)
}
}
// 사용자가 카메라를 사용해 찍고 돌아왔는지, 안 찍고 돌아왔는지에 따라 분기해 다르게 처리하는 등의 경우에 필요
//startActivityForResult 는 decrated 되어 launcher 를 사용한 방식 공부 필요
private val activityResultLauncher : ActivityResultLauncher<Intent> = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
){
//Log.d("test","콜백이 메서드가 실행....")
// SubOne에서 결과를 받아옴
if (it.resultCode == 100){
binding.textView.text = "두번째 액티비티에서 돌아왔습니다.\n"
//객체를 추출
val obj2 = it.data?.getParcelableExtra<TestClass>("obj2")
binding.textView.append("obj2.data1 : ${obj2?.data1}\n")
binding.textView.append("obj2.data2 : ${obj2?.data2}")
}
else if (it.resultCode == 200) {
binding.textView.text = "세번째 액티비티에서 돌아왔습니다.\n"
}
}
[SecondActivity.kt]
val obj1 = intent.getParcelableExtra<TestClass>("obj1")
//parcel 객체에 있는 변수의 값을 추출하고 TestClass 객체를 만들어 집어넣
second_binding.textView2.text = "obj1.data1 : ${obj1?.data1}\n"
second_binding.textView2.append("obj1.data2 : ${obj1?.data2}")
second_binding.button2.setOnClickListener {
val t2 = TestClass()
t2.data1 = 200
t2.data2 = "문자열2"
val result_intent = Intent()
result_intent.putExtra("obj2",t2)
setResult(100,result_intent) // resultCode : code 값, Intent(선택적) : 전달할 데이터를 Intent 객체로 만들어 저장
finish() // 현재 액티비티 종료
}
[TestClass.kt]
class TestClass() : Parcelable{
var data1 : Int = 0
var data2 : String? = ""
// createFromParcel() 에서 사용되는 생성자
constructor(parcel: Parcel) : this() {
data1 = parcel.readInt() //default = 0
data2 = parcel.readString() //default = null 이므로 변수에 null 허용 해줘야 함
}
// putExtra를 이용해 객체를 인텐트에 담는 작업을 할 경우 호출되는 메서드
// TestClass 객체가 intent에 저장되는 것이 아닌 객체를 구성하는 변수의 값이 저장
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(data1)
parcel.writeString(data2)
}
override fun describeContents(): Int {
return 0
}
// 객체 전달 후 추출등의 과정에서 호출
companion object CREATOR : Parcelable.Creator<TestClass> { // companion은 static 객체 같은것
// getParcelableExtra 를 호출해서 객체를 추출하려고 하면 자동으로 호출되는 메서드
// 새로운 객체를 생성하고 parcel에 저장되어 있는 데이터를 추출해 객체의 변수에 담아줌
// 그 후 생성된 객체를 반환
override fun createFromParcel(parcel: Parcel): TestClass {
return TestClass(parcel) //Parcel 객체를 매개변수로 넣어 TestClass 객체를 생성해 반환
}
override fun newArray(size: Int): Array<TestClass?> {
return arrayOfNulls(size)
}
}
}
반응형
'Android' 카테고리의 다른 글
[안드로이드/Build Error] Appcompat 버전 문제 (0) | 2023.03.25 |
---|---|
[안드로이드/Activity] 다른 애플리케이션의 액티비티 실행 (0) | 2023.03.25 |
[안드로이드/Activity] 데이터 전달 (0) | 2023.03.18 |
[안드로이드] CallBack 과 Listener (0) | 2023.03.11 |
[안드로이드/Activity] OnActivityResult 와 registerForActivityResult (0) | 2023.03.10 |