[Android] Activity 데이터 전달 with ActivityResultLauncher

💡 ActivityResultLauncher를 활용한 액티비티 간 데이터 전달을 기록하였습니다 !

 

단방향 데이터 전달

  • Activity 간 단방향 데이터 전달은 Intent를 통해 이루어집니다.

Intent  |  Android Developers

 

Intent  |  Android Developers

 

developer.android.com

데이터 전달하기

  • 시작할 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

 

런타임 권한 요청  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 런타임 권한 요청 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 모든 Android 앱은 액세스가 제한된 샌

developer.android.com

 

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를 사용하는 것이 유용할 것 같습니다 !

참고

https://kkangsnote.tistory.com/185