Android & Kotlin

[ Android ] startActivityForResult deprecated 이유와 대안( Activity Result API)

쉽코기 2022. 2. 15. 23:49

 

0. StartActivity vs startActivityForResult (ActivityResult )

 

 

앨범에서 사진을 가져오는 상황과 같이 Activity끼리의 양방향 통신이 필요할 때 startActivityForResult 함수를 써왔습니다.

 

StartActivity 는 단순히 Activity:  A -> B 로의 화면전환이라면

StartAcivityForResult 는 A -> B -> A 인 상황에서 A로 돌아올 때 B에서의 정보를 가져온다. A 에서 함수를 호출해서 B로 가고, B에서 작업을 마치고 필요한 데이터를 가지고 다시 A 로 돌아왔음을 알 수 있는 방법입니다.

 

이동할 Activity 나 Fragment 자체에 리스너를 넘길 수 없으니 B에서 A 로 돌아왔을 때 특정 행동을 즉시 실행하는데 있어서 좋은 해결책이 되어 왔습니다.

그러나 현재는 deprecated 상태로 그 대안인 Activity Result API 를 정리해보려 합니다.

 

 

 

https://developer.android.com/training/basics/intents/result

 

활동에서 결과 가져오기  |  Android 개발자  |  Android Developers

활동에서 결과 가져오기 개발자 앱 내의 활동이든 다른 앱의 활동이든 다른 활동을 시작하는 것이 단방향 작업일 필요는 없습니다. 다른 활동을 시작하고 다시 결과를 받을 수도 있습니다. 예를

developer.android.com

 

1. startAcitivytForResult 가 deprecated  이유

 

가장 큰 문제는 startActivityForResult 에 의해 로직이 수행되는 와중에 응답을 받을 Activity가  메모리 부족으로 인해 사라지는 경우가 존재한다는 것입니다. 이미지를 가져오는 상황에서 큰 메모리를 처리하면서 이런 현상을 쉽게 마주할 수 있었습니다. 그러나 startActivityForResult 는 이런 상황에 대처하지 못해왔습니다. 

 

위 문제를  Acitity Result Api 는 해결하고 있습니다.

 

2. Activity Result API  소개

 

Activity Result Api 는 크게 콜백을 받는 부분과 화면을 전환하는 부분을 반드시 분리하여 구성합니다.

일반적으로 이벤트가 발생했을때 화면전환이 이루어지고 이부분에서 전환과 함께 리시버를 생성 한다면 돌아올 Acitivity 가 사라진 경우 재 생성하게 되더라도 리시버를 찾을 수 없게 됩니다.

 

registerForActivityResult 함수는 콜백을 등록해주는 역할을 수행합니다. 이를 통해서 메모리 부족으로 시작점의 Activity 가 꺼진다고 하더라도 다시 생성되었을때 결과를 기다리고 있다는 것을 알려줄 수 있습니다. 그러나 직접 적으로 화면을 전환하는 함수는 registerForActivityResult 를 통해 만들어진 객체(ActivityResultLauncher)에 launch 를 호출하는 것으로 이루어 집니다.

 

3. 사용법

 

1. build gradel 에 dependecy 를 추가해한다.

implementation 'androidx.activity:activity-ktx:1.2.0-alpha02'
implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha02'

 

2.  MainActivity (출발 Activity , 응답을 받을 대상)

// Activity Class
val getResult =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                if (it.resultCode == RESULT_OK) {
                        Snackbar.make(constLaytout!!, "사진을 불러옵니다", Snackbar.LENGTH_SHORT).show()
                }
            }
            
// onCreate            
        myButton.setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            getResult.launch(intent)
        }

 

3. SecondActivity (도착 Activity , 응답을 줄 대상)

  btn_close.setOnClickListener {
            setResult(RESULT_OK)
            finish()
        }