💡 ActivityResultLauncher를 활용한 액티비티 간 데이터 전달을 기록하였습니다 !
단방향 데이터 전달
- Activity 간 단방향 데이터 전달은 Intent를 통해 이루어집니다.
데이터 전달하기
- 시작할 Intent에 putExtra나 putSerializable을 활용해서 데이터를 전달할 수 있습니다.
- CLUB_MODIFY_UI_MODEL이라는 key를 통해서 clubModifyUiModel을 전달하였습니다.
fun getIntent(
context: Context,
clubModifyUiModel: ClubModifyUiModel,
): Intent {
return Intent(context, ClubModifyActivity::class.java).apply {
putSerializable(
ClubModifyActivity.CLUB_MODIFY_UI_MODEL,
clubModifyUiModel,
ClubModifyUiModel.serializer(),
)
}
}
- 이 후에 startActivity를 통해 해당 Intent를 실행해주는 방법으로 데이터를 전달할 수 있습니다.
override fun navigateToModify() {
val clubModifyUiModel = viewModel.makeClubModifyUiModel() ?: return
val modifyIntent = makeModifyIntent(clubModifyUiModel)
startActivity(modifyIntent)
}
private fun makeModifyIntent(modifyUiModel: ClubModifyUiModel): Intent {
return ClubModifyActivity.getIntent(
this@ClubDetailActivity,
modifyUiModel,
)
}
데이터 받기
- 데이터를 받는 곳에서 데이터를 보낸 곳과 같은 key 값을 활용해서 데이터를 전달 받습니다.
private fun initUiModel() {
val clubModifyUiModel =
intent.intentSerializable(ClubModifyActivity.CLUB_MODIFY_UI_MODEL, ClubModifyUiModel.serializer())
clubModifyUiModel?.let {
viewModel.initUiModel(
clubModifyUiModel = clubModifyUiModel,
)
}
}
양방향 데이터 전달
- Android에서 액티비티 간에 양방향 데이터 전달을 위해선 ActivityResultLauncher를 활용해야 합니다.
- 기존의 startActivityForResult() 및 onActivityResult()를 활용한 기존 방식은 더 이상 권장되지 않습니다.
ActivityResultLauncher
- ActivityResultLauncher는 새롭게 개선된 방법을 제공합니다.
- 이 API를 통해 액티비티나 프래그먼트를 시작하고, 그 결과를 쉽게 처리할 수 있습니다.
- androidx에서 제공하는 기능이며 인텐트를 발생시키고 결과를 되돌려 받는 기능을 제공합니다.
ActivityResultLauncher 구조
- ActivityResultLauncher는 Callback과 Contract 구조로 이루어져 있습니다.
- ActivityResultLauncher에 Contract와 Callback 객체를 등록한 후 launch() 함수로 실행합니다.
- 이 후 ActivityResultLauncher에 등록된 Contract 객체가 실행 요청을 처리하여 그 결과를 Callback에 전달하여 사후 처리가 되도록 하는 구조입니다.
Contract
- ActivityResultLauncher를 상속받은 서브 클래스이며, 직접 만들거나 API에서 제공되는 클래스를 이용합니다.
- 아래와 같은 클래스를 제공합니다.
- [PickContract] : 선택한 연락처의 Uri 획득
- [RequestPermission] : 권한 요청, 허락 여부 파악
- [RequestMultiplePermissions] : 여러 권한을 동시에 요청
- [StartActivityForResult] : 인텐트 발생으로 액티비티 실행, 결과 획득
- [TakePicturePreview] : 사진 촬영 후 비트맵 획득
- [TakePicture] : 사진 촬영, 저장, 비트맵 획득
- ActivityResultLauncher로 액티비티를 실행시키고 StartActivityForResult를 통해 결과를 받습니다.
런타임 권한 요청 | Android Developers
Intent와 ActivityResultLauncher
- Intent와 ActivityResultLauncher를 활용해 종료 된 액티비티로부터 결과를 전달 받는 코드를 작성하였습니다.
ActivityResultLauncher 생성 및 초기화
- ClubDetailActivity 에서 다음 액티비티로 이동 시 전달할 Launcher를 생성하였습니다.
private lateinit var clubModifyResultLauncher: ActivityResultLauncher<Intent>
- ActivityResultLauncher의 초기화를 onCreate에서 하기 위해서 늦은 초기화인 lateinit으로 선언하였습니다.
- ActivityResultContracts.StartActivityForResult() 를 통해 Result를 받기 위한 Contracts 임을 명시하였습니다.
- 콜백을 통해 result를 받을 수 있으며, resultCode가 전달 받은 값의 code와 같아야 전달받도록 합니다.
clubModifyResultLauncher =
registerForActivityResult(
ActivityResultContracts.StartActivityForResult(),
) { result -> // 콜백 처리
if (result.resultCode == Activity.RESULT_OK) {
// 같은 resultCode일 때 내부 로직을 수행합니다.
val isModify =
result.data?.getBooleanExtra(
ClubModifyActivity.SUCCESS_MODIFY_STATE,
false,
)
?: false
if (isModify) {
putLoadState()
viewModel.loadClub(receiveClubId())
}
}
}
다음 액티비티로 전달
- 단방향 데이터와 마찬가지로 Intent를 통해 전달하며, startActivity가 아닌 launch를 활용해 실행합니다.
override fun navigateToModify() {
val clubModifyUiModel = viewModel.makeClubModifyUiModel() ?: return
val modifyIntent = makeModifyIntent(clubModifyUiModel)
clubModifyResultLauncher.launch(modifyIntent)
}
이전 액티비티로 전달
- 이동한 액티비티에서 작업을 완료한 후 이전 액티비티로 데이터를 전달할 수 있습니다.
- AppCompatActivity.RESULT_OK를 전달하여 같은 resultCode로 데이터를 전달해줍니다.
ClubModifyEvent.Navigation.NavigateSubmit -> {
intent.putExtra(ClubModifyActivity.SUCCESS_MODIFY_STATE, true)
setResult(AppCompatActivity.RESULT_OK, intent)
finish()
}
정리
ActivityResultLauncher는 더 간결하고 유지 보수하기 쉬운 코드 작성을 돕는 유용한 도구로 활용될 수 있습니다.
Android에서 최신 권장 사항을 따르는 개발자라면 이 API를 사용하는 것이 유용할 것 같습니다 !