DEV Community

Sewon Ann
Sewon Ann

Posted on

ActivityResultContract ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ

์•ˆ๋“œ๋กœ์ด๋“œ๋Š” intent ๋ฅผ ์ด์šฉํ•ด ๋‹ค๋ฅธ ์•ฑ์˜ ๊ธฐ๋Šฅ์„ ์œ ์—ฐํ•˜๊ฒŒ ํ˜ธ์ถœํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜์ธ startActivityForResult์™€ onActivityResult๋Š” ํŽธ๋ฆฌํ•ด ๋ณด์ด์ง€๋งŒ, ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํ•จ์ •์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋‹ค. ์ด ๊ธ€์—์„  ์ƒˆ๋กœ์šด ํ‘œ์ค€์ด ๋œ Activity Result API์™€ ActivityResultContract์— ๋Œ€ํ•ด ๊นŠ์ด ํŒŒํ—ค์ณ ๋ณด๊ณ , ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•  ์ ๊นŒ์ง€ ํ•จ๊ป˜ ์•Œ์•„๋ณด๊ฒ ๋‹ค.

ActivityResultContract ์†Œ๊ฐœ

ActivityResultContract ๋Š” ๋‹ค๋ฅธ ์•กํ‹ฐ๋น„ํ‹ฐ๋ฅผ ์‹คํ–‰ํ•˜๊ณ , ๊ทธ๋กœ๋ถ€ํ„ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ์ž‘์—…์„ ์ถ”์ƒํ™”ํ•œ ํด๋ž˜์Šค๋‹ค. ์ด ํด๋ž˜์Šค๋Š” ๋‘ ๊ฐ€์ง€ ํƒ€์ž…, ์ฆ‰ ์ž…๋ ฅ(Input)๊ณผ ์ถœ๋ ฅ(Output)์„ ์ œ๋„ค๋ฆญ์œผ๋กœ ๋ฐ›๋Š”๋‹ค. createIntent ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ž…๋ ฅ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ธํ…ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , parseResult ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด onActivityResult ์ฝœ๋ฐฑ์œผ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅ ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๊ณผ๊ฑฐ์˜ ์œ ์‚ฐ: onActivityResult

ActivityResultContract๊ฐ€ ๋“ฑ์žฅํ•˜๊ธฐ ์ „์—๋Š” ๋‹ค๋ฅธ ์•กํ‹ฐ๋น„ํ‹ฐ๋กœ๋ถ€ํ„ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›๊ธฐ ์œ„ํ•ด startActivityForResult์™€ onActivityResult๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

Activity์—์„œ onActivityResult ์‚ฌ์šฉํ•˜๊ธฐ

class OldActivity : AppCompatActivity() {

    val REQUEST_CODE = 123

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        val intent = Intent(this, OtherActivity::class.java)
        startActivityForResult(intent, REQUEST_CODE)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            // ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

์ด ๋ฐฉ์‹์€ requestCode๋ฅผ ์‚ฌ์šฉํ•ด ์—ฌ๋Ÿฌ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋ถ„ํ•ด์•ผ ํ–ˆ๊ณ , onActivityResult ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์— ๋ณต์žกํ•œ ์กฐ๊ฑด๋ฌธ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ๋‹ค. ๋˜ํ•œ, Activity ํด๋ž˜์Šค์— ์ง์ ‘ ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์œ ๋‹› ํ…Œ์ŠคํŠธ๊ฐ€ ์–ด๋ ค์›Œ์ง€๋Š” ๋ฌธ์ œ๋„ ์žˆ์—ˆ๋‹ค.

Fragment์—์„œ onActivityResult ์‚ฌ์šฉํ•˜๊ธฐ

Fragment ์—ญ์‹œ onActivityResult๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

class OldFragment : Fragment() {

    override fun onStart() {
        super.onStart()
        val intent = Intent(requireContext(), OtherActivity::class.java)
        startActivityForResult(intent, REQUEST_CODE)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            // ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Fragment ์—ญ์‹œ Activity์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ onActivityResult๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์•ผ ํ–ˆ์œผ๋ฉฐ, ์ด๋Š” ๋น„์Šทํ•œ ๋‹จ์ ๋“ค์„ ์•ผ๊ธฐํ–ˆ๋‹ค.

ActivityResultContract์˜ ๋‚ด๋ถ€ ๋™์ž‘: Registry๋ฅผ ํ†ตํ•œ ์ถ”์ƒํ™”

๋งŽ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ActivityResultContract๊ฐ€ ์™„์ „ํžˆ ์ƒˆ๋กœ์šด ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ, ์‚ฌ์‹ค ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์—ฌ์ „ํžˆ startActivityForResult์™€ onActivityResult๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ActivityResultContract๋Š” ์ด ๋‘ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ๋Œ€์‹ , ActivityResultRegistry ๋ฅผ ํ†ตํ•ด ์ด๋ฅผ ์ถ”์ƒํ™”ํ•˜๊ณ  ๊ด€๋ฆฌํ•œ๋‹ค.

ActivityResultRegistry๋Š” ์ƒ๋ช…์ฃผ๊ธฐ์— ์•ˆ์ „ํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฆฌ์Šค๋„ˆ์™€ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. registerForActivityResult๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ ๊ณผ์ •์ด ์ง„ํ–‰๋œ๋‹ค.

  1. ํ‚ค ์ƒ์„ฑ: ActivityResultRegistry๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ๊ณ ์œ ํ•œ ํ‚ค(์˜ˆ: "activity_rq#1")๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ฐธ๊ณ : ComponentActivity#registerForActivityResult
  2. ๋ฆฌ์Šค๋„ˆ ๋“ฑ๋ก: ์ด ๊ณ ์œ ํ•œ ํ‚ค์™€ ํ•จ๊ป˜, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ œ๊ณตํ•œ ์ฝœ๋ฐฑ(ActivityResultCallback)์ด ActivityResultRegistry์— ๋“ฑ๋ก๋œ๋‹ค. ์ฐธ๊ณ : ActivityResultRegistry#register

์ด์ œ ActivityResultLauncher์˜ launch ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด, ActivityResultRegistry๋Š” ์ค€๋น„๋œ ์ธํ…ํŠธ๋ฅผ startActivityForResult๋ฅผ ์ด์šฉํ•ด ์‹คํ–‰ํ•œ๋‹ค. ( ์ฐธ๊ณ  : ComponentActivity.activityResultRegistry) ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์ข…๋ฃŒ๋˜์–ด ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋˜๋ฉด, onActivityResult๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋œ ๊ฒฐ๊ณผ๋ฅผ ActivityResultRegistry๊ฐ€ ๊ฐ€๋กœ์ฑˆ๋‹ค. (์ฐธ๊ณ : ComponentActivity#onActivityResult)

๋งˆ์ง€๋ง‰์œผ๋กœ, ActivityResultRegistry๋Š” ์ฒ˜์Œ ๋“ฑ๋กํ–ˆ๋˜ ๊ณ ์œ ํ•œ ํ‚ค๋ฅผ ์ด์šฉํ•ด ๋“ฑ๋ก๋œ ์ฝœ๋ฐฑ์„ ์ฐพ์•„ onResult๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค. ์ด ๋ชจ๋“  ๊ณผ์ •์ด ActivityResultContract ๋’ค์— ์ˆจ๊ฒจ์ ธ ์žˆ์–ด ๊ฐœ๋ฐœ์ž๋Š” ๋ณต์žกํ•œ ์ฝœ๋ฐฑ ์ฒ˜๋ฆฌ๋ฅผ ์ง์ ‘ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

์ด ๊ณผ์ •์„ sequence diagram ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

ActivityResultContract ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•  ์ 

ActivityResultContract๋Š” ๋ถ„๋ช… ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ด์ง€๋งŒ, ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฒ„๊ทธ๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์›์น™์€ registerForActivityResult() ๋Š” ํ•ญ์ƒ ๊ฐ™์€ ์ˆœ์„œ๋กœ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

Activity์—์„œ ์‚ฌ์šฉํ•  ๋•Œ

Activity์—์„œ registerForActivityResult๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋Š” ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์‹œ์ ์— ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.

class NewActivity : AppCompatActivity() {

    // ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ์ดˆ๊ธฐํ™”
    private val someActivityResultLauncher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        // ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        someActivityResultLauncher.launch(intent)
    }
}
Enter fullscreen mode Exit fullscreen mode

๋งŒ์•ฝ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ํ˜ธ์ถœ ์ˆœ์„œ๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค๋ฉด ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ? ์ด๋Ÿฐ ์‹์œผ๋กœ ์งœ๋ฉด ์•ˆ๋˜์ง€๋งŒ ํ•˜์—ฌ๊ฐ„ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ƒ์ƒํ•ด๋ณด์ž.

class NewActivity : AppCompatActivity() {

    lateinit var someActivityResultLauncher : ActivityResultLauncher<Intent>
    lateinit var otherActivityResultLauncher : ActivityResultLauncher<Intent>

     init {
         val isAm = ZonedDateTime.now().hour < 12

         if( isAm) {
             someActivityResultLauncher = registerForActivityResult(..) { }
             otherActivityResultLauncher = registerForActivityResult(...) { }
         } else {
             otherActivityResultLauncher = registerForActivityResult(...) { }
             someActivityResultLauncher = registerForActivityResult(...) { }
         }
     }
}

Enter fullscreen mode Exit fullscreen mode

์˜ค์ „์— ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์ƒ์„ฑ๋˜์–ด some > other ์ˆœ์œผ๋กœ register ๋˜์—ˆ๋‹ค. ์ด ๊ฒฝ์šฐ some ์˜ ๋‚ด๋ถ€ key๋Š” activity_req#0, other ๋Š” activity_req#1 ์ด ๋œ๋‹ค. some ์„ launch ํ•ด์„œ ๋‹ค๋ฅธ OtherActivity ๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋‹ค. ๊ทธ ์‚ฌ์ด์— ์˜คํ›„๊ฐ€ ๋˜์—ˆ๋‹ค. ๊ทธ ์‚ฌ์ด์— ์‚ฌ์šฉ์ž๊ฐ€ ํ™”๋ฉด์„ ํšŒ์ „ํ•ด์„œ NewActivity ๋Š” ์žฌ์ƒ์„ฑ๋˜์–ด์•ผ ํ•œ๋‹ค. ์ด์ œ OtherActivity๊ฐ€ ์žฌ์ƒ์„ฑ๋˜๋ฉด์„œ ๊ฒฐ๊ณผ๊ฐ’์ด ์ „๋‹ฌ๋œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด๋ฒˆ์—” other ๊ฐ€ #0, some ์ด #1 ์ด ๋˜์–ด๋ฒ„๋ ธ๋‹ค. ๊ฒฐ๊ตญ some ์˜ callback ์ด ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ, ์—‰๋šฑํ•˜๊ฒŒ other ์˜ callback ์ด ํ˜ธ์ถœ๋˜์–ด ๋ฒ„๋ฆฐ๋‹ค. ๋งŒ์•ฝ ๋‘ callback ์˜ ์ธ์ž ํƒ€์ž…์ด ๋‹ค๋ฅผ ๊ฒฝ์šฐ์—” class cast exception ์ด ๋‚  ์ˆ˜๋„ ์žˆ๊ณ , ์•„๋‹ˆ๋ฉด ๊ฐ€์ ธ์˜จ ๊ฒฐ๊ณผ๊ฐ’์œผ๋กœ ์—‰๋šฑํ•œ ์ผ์ด ๋ฒŒ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์˜๋ฌธ์ด ํ•œ๊ฐ€์ง€ ๋“ค ์ˆ˜ ์žˆ๋‹ค. startActivityForResult() ์— ์ „๋‹ฌ๋˜๋Š” request code ๋Š” ๋žœ๋คํ•˜๊ฒŒ ์ƒ์„ฑ๋˜๋Š”๋ฐ, ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์žฌ์ƒ์„ฑ๋˜์—ˆ์„ ๋•Œ onActivityResult ์—์„œ ์ด์ „ request code ๋ฅผ ์–ด๋–ป๊ฒŒ ์•Œ๊ณ  callback ์„ ํ˜ธ์ถœํ•˜๋Š”๊ฑธ๊นŒ? ์ด ๋ถ€๋ถ„์€ ActivityResultRegistry ๊ฐ€ ์žฌ์ƒ์„ฑ ์‹œ ๋ณต๊ตฌ๋˜๋ฉด์„œ ๊ธฐ์กด ๋‚ด๋ถ€ key ์™€ request code ๊ฐ„ ๋งคํ•‘์„ ๋ณต๊ตฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•Ÿ.

ActivityResultRegistry ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ launcher ๋“ค์— ๋ถ€์—ฌ๋œ key ๋ฅผ Int ํƒ€์ž…์ธ request code ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ…Œ์ด๋ธ”์„ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉฐ ( ์ฐธ๊ณ : ActivityResultRegistiry#bindRcKey) , ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์žฌ์ƒ์„ฑ๋  ๋•Œ ์ด ํ…Œ์ด๋ธ”์„ ๋ณต๊ตฌํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์žฌ์ƒ์„ฑ๋˜์–ด๋„ ์ด์ „์— ํ˜ธ์ถœํ–ˆ๋˜ request code ๋ฅผ ๊ฐ€์ง€๊ณ  ์–ด๋–ค ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•ด์•ผ ํ•  ์ง€ ์ž˜ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ( ์ฐธ๊ณ  : ActivityResultRegistry#onRestoreInstanceState)

Fragment์—์„œ ์‚ฌ์šฉํ•  ๋•Œ

Fragment ์—ญ์‹œ Activity์™€ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ถ”๊ฐ€์ ์œผ๋กœ Fragment๊ฐ€ destroy๋œ ํ›„ ๋‹ค์‹œ create๋  ๋•Œ, ์ด์ „์— ๋“ฑ๋กํ–ˆ๋˜ ์ฝœ๋ฐฑ ์ •๋ณด๊ฐ€ ์‚ฌ๋ผ์ ธ ์ฝœ๋ฐฑ์ด ์ œ๋Œ€๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” Fragment๊ฐ€ destroy๋  ๋•Œ ActivityResultRegistry์— ๋“ฑ๋ก๋œ ์ •๋ณด๊ฐ€ ์ œ๊ฑฐ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

lifecycleOwner ๊ฐ€ DESTROY ๋  ๋•Œ ๋“ฑ๋ก๋œ contract, callback ์„ unregister ํ•˜๋Š” ๋™์ž‘์€ ์–ด์ฐจํ”ผ ActivityResultRegistry๊ฐ€ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Activity ๋‚˜ Fragment ๋‚˜ ๋™์ผํ•˜๋‹ค. ํ•˜์ง€๋งŒ ๋‚˜๋Š” ํ•œ๋ฒˆ destroy ๋œ Activity ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‹ค์‹œ create ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ๋Š”๋ฐ, Fragment ์—์„  ์ด๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ ์ข…์ข… ๋ดค๋‹ค. ๋”ฐ๋ผ์„œ, Activity ์—์„  ๊ฐ์ฒด ์ดˆ๊ธฐํ™” ์‹œ register ๋ฅผ ๊ถŒ์žฅํ–ˆ์ง€๋งŒ Fragment ์—์„  ์˜คํžˆ๋ ค onCreate ์—์„œ register ๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค. ์ด๋ž˜์•ผ destroy ํ›„ re-create ์‹œ ๋‹ค์‹œ ActivityResultRegistry ์— Launcher๊ฐ€ ๋“ฑ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋”ฐ๋ผ์„œ Fragment ์ธ์Šคํ„ด์Šค ์ดˆ๊ธฐํ™” ์‹œ์ ๋ณด๋‹ค๋Š” onCreate ์ฝœ๋ฐฑ ๋‚ด์—์„œ registerForActivityResult๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ๋” ์•ˆ์ „ํ•˜๋‹ค.

class NewFragment : Fragment() {

    private lateinit var someActivityResultLauncher: ActivityResultLauncher<Intent>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Fragment๊ฐ€ ์žฌ์ƒ์„ฑ๋  ๋•Œ๋งˆ๋‹ค ์ฝœ๋ฐฑ์ด ๋‹ค์‹œ ๋“ฑ๋ก๋˜๋„๋ก ๋ณด์žฅ
        someActivityResultLauncher = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) { result ->
            // ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ
        }
    }

    fun someButtonClick() {
        someActivityResultLauncher.launch(Intent(requireContext(), OtherActivity::class.java))
    }
}
Enter fullscreen mode Exit fullscreen mode

Composable์—์„œ ์‚ฌ์šฉํ•  ๋•Œ

Jetpack Compose์—์„œ๋Š” rememberLauncherForActivityResult ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ํ•จ์ˆ˜ ์—ญ์‹œ ๋‚ด๋ถ€์ ์œผ๋กœ activityResultRegistry.register๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, Activity ๋‚˜ Fragment ์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค.

@Composable
fun MyScreen() {
    val someActivityResultLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartActivityForResult(),
        onResult = { result ->
            // ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ
        }
    )

    Button(onClick = {
        someActivityResultLauncher.launch(Intent(context, OtherActivity::class.java))
    }) {
        Text("Launch Activity")
    }
}
Enter fullscreen mode Exit fullscreen mode

๋‹ค๋งŒ ๋‚ด๋ถ€ key ๊ฐ€ UUID.randomUUID().toString() ๋ผ์„œ, Activity ์—์„œ activity_req#1 ์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ๋“ฑ๋ก ์ˆœ์„œ์— ์˜ํ–ฅ์„ ๋ฐ›๋Š”๊ฒŒ ์•„๋‹Œ, ๋žœ๋คํ•œ ๊ณ ์œ ๊ฐ’์ด ๋ถ€์—ฌ๋˜๋Š” ๋ถ€๋ถ„์ด ๋‹ค๋ฅด๋‹ค.

rememberLauncherForActivityResult๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์กฐ๊ฑด๋ฌธ ์•ˆ์— ๋“ฑ๋กํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. remember๊ฐ€ ์žˆ๋Š” ํ•จ์ˆ˜๋Š” ์ปดํฌ์ €๋ธ”์˜ ์žฌ๊ตฌ์„ฑ(recomposition) ๊ณผ์ •์—์„œ remember์˜ ํ‚ค๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ฑฐ๋‚˜ ์กฐ๊ฑด์— ๋”ฐ๋ผ ํ˜ธ์ถœ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ, ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜ ์•„์˜ˆ ์ƒ์„ฑ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋˜ํ•œ, rememberLauncherForActivityResult๋Š” ๊ฐ€๊ธ‰์  ์ตœ์ƒ์œ„ ์ปดํฌ์ €๋ธ”์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค. ํ•˜์œ„ ์ปดํฌ์ €๋ธ”์—์„œ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ์ƒ์œ„ ์ปดํฌ์ €๋ธ”์˜ ์ƒํƒœ ๋ณ€ํ™”๋‚˜ ์กฐ๊ฑด๋ฌธ์— ๋”ฐ๋ผ ์ปดํฌ์ €๋ธ”์˜ ์œ„์น˜ ๋“ฑ์ด ๋ฐ”๋€” ๊ฒฝ์šฐ ์•กํ‹ฐ๋น„ํ‹ฐ ์žฌ์ƒ์„ฑ ์‹œ ๋‹ค๋ฅธ composable ๋กœ ์ธ์‹๋˜์–ด ์ด์ „ composable ์˜ ๋ณต๊ตฌ๊ฐ€ ์ด๋ค„์ง€์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ฒฐ๊ณผ ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์บก์Аํ™” ๊ด€์ ์—์„œ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•˜๋Š” composable ๋‚ด๋ถ€์— rememberLauncherForActivityResult ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฐธ ํŽธ๋ฆฌํ•˜๊ฒ ์ง€๋งŒ, ํ•ด๋‹น composable ์ด ์–ด๋–ค ๋งฅ๋ฝ์—์„œ, ์–ด๋–ค ๊ฒฝ์šฐ์— ํ˜ธ์ถœ๋˜๋Š”์ง€ ํ†ต์žฌํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๊ฑด ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ๊ฒŒ์‹œํŒ์„ ๋งŒ๋“œ๋Š”๋ฐ ๋Œ“๊ธ€ composable ์— ์ด๋ฏธ์ง€ ์ฒจ๋ถ€๋ฅผ ์œ„ํ•ด ๊ฐค๋Ÿฌ๋ฆฌ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ธฐ๋Šฅ๊นŒ์ง€ ๋„ฃ์–ด๋‘๋ฉด ์ฐธ ๋ฉ‹์งˆ ๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ ์ด ๋Œ“๊ธ€ composable ์ด ์–ด๋–ค ์‹์œผ๋กœ ํ˜ธ์ถœ๋ ์ง€ composable ์ž‘์„ฑ์ž๊ฐ€ ์ปจํŠธ๋กค ํ•  ์ˆ˜ ์—†๊ณ , ์ด๋Ÿฌ๋‹ค๋ณด๋ฉด ์•กํ‹ฐ๋น„ํ‹ฐ ์žฌ์ƒ์„ฑ ์‹œ ํ˜ธ์ถœ ์œ„์น˜๊ฐ€ ๋ฐ”๋€Œ์–ด๋ฒ„๋ฆด ๊ฒฝ์šฐ ์ฐพ๊ธฐ ์–ด๋ ค์šด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค. ๋ฐ˜๋Œ€๋กœ composable ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž ์ž…์žฅ์—์„œ๋„ ์ด composable์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์–ด๋–ค ์ฃผ์˜์‚ฌํ•ญ์ด ์žˆ๋Š”์ง€ ์ผ์ผ์ด ํŒŒ์•…ํ•˜๊ธฐ๊ฐ€ ์‰ฝ์ง€ ์•Š์•„, ์ด๋Ÿฐ ๊ฒฝ์šฐ ์• ์ดˆ์— rememberLauncherForActivityResult ๋ฅผ ์•ˆ์“ฐ๋Š”๊ฒŒ ๋‚ซ๋‹ค.

๋”ฐ๋ผ์„œ ๊ฐ€๊ธ‰์  ์ตœ์ƒ์œ„ composable ์—๋งŒ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์œ ์ง€๋ณด์ˆ˜ ๊ด€์ ์—์„œ ๋” ๋‚˜์€ ์„ ํƒ์ด ๋  ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•œ๋‹ค.

๋งบ์Œ๋ง

ActivityResultContract๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ , ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ์ œ๊ณตํ•˜๋ฉฐ, ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค. ํ•˜์ง€๋งŒ ์ฃผ์˜๊นŠ๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์ฐพ๊ธฐ ์–ด๋ ค์šด ์ด์ƒ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ž˜ ์•Œ๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

Top comments (2)

Collapse
 
fred_functional profile image
Fred Functional

์ข‹์€ ์ •๋ฆฌ์ž…๋‹ˆ๋‹ค! ์ฐธ๊ณ ๋กœ AndroidX Fragment 1.3.0๋ถ€ํ„ฐ Fragment์˜ startActivityForResult/onActivityResult๋Š” deprecated์ด๊ณ , Compose์˜ rememberLauncherForActivityResult๋Š” ๋‚ด๋ถ€ ํ‚ค๋ฅผ UUID๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ requestCode๋Š” ๋กœ๋˜ ๋ฒˆํ˜ธ์ฒ˜๋Ÿผ ์žŠ์–ด๋„ ๋˜์ง€๋งŒ, register ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์ฝœ๋ฐฑ๋„ ์นดํŽ˜์ธ ๋Œ€์‹  ๋ฒ„๊ทธ๋ฅผ ๋“œ๋ฆฝํ•ด์š” :)

Collapse
 
kingori profile image
Sewon Ann

๋„ค, ๋งž์Šต๋‹ˆ๋‹ค. register ์ˆœ์„œ๋Š” ๊ผญ ์ง€์ผœ์•ผํ•˜์ง€์š”.