#What
startActivityForResult -> onActivityResult 짝꿍이 Deprected 됐으므로 대체 API를 알아봅시다.
1)일반적인 Activity이동
*디벨러퍼에서도 AndroidX를 사용한다면 대체 API를 사용하라고 적극 권장 중입니다
it is strongly recommended to use the Activity Result APIs introduced in AndroidX Activity and Fragment.
https://developer.android.com/training/basics/intents/result
#기존 방식
startActivityForResult을 RequestCode를 인자로 호출 후, onActivityResult에서 RequestCode 분기 후 결과 처리
#대체 방식
=> registerForActivityResult 를 사용
인자 : 1) ActivityResultContracts 2) ActivityResultCallback
리턴 : ActivityResultLauncher (activity 시작할 수 있게 해쥼)
lateinit var launcher: ActivityResultLauncher<Intent>
override fun onCreate(savedInstanceState: Bundle?) {
...
//1) intent 생성 = 기존 동일
val intent = Intent(applicationContext, SecondActivity::class.java)
//2) resultCallback 등록 후 ActivityResultLauncher 멤버로 저장
launcher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult(), // 인자 1) Contract
ActivityResultCallback<ActivityResult> { result -> // 인자 2) ActivityResultCallback
val resultCode = result.resultCode
val dataIntent = result.data
Log.i("syTest","result : ${result.toString()}")
}
)
findViewById<TextView>(R.id.tv_hello).setOnClickListener {
//실제 activity 이동 코드
launcher.launch(intent)
}
}
}
- Intent 작성법은 기존과 동일
- ActivityResultCallback이 기존의 onActivityResult(int requestCode, int resultCode, Intent data) 를 대신함
- launch 요청 마다 각각의 ActivityResultCallback이 등록돼있으므로, requestCode가 사라짐
- ActivityResultContracts에 미리 정의 돼 있는 StartActivityForResult()를 가져와 사용할 수 도 있고, Custom ActivityResultContract를 재정의해 사용할 수 도 있음
#왜 callback 등록과, 액티비티 launch를 분리했을까?
[자체 해석...]
startActivityForResult 호출로 카메라와 같은 메모리 사용량이 많은 작업을 실행하는 경우 process와 activity가
destory 되는경우가 발생합니다.
이 때문에 Activity Result API는 (카메라) 호출을 실행한 Code와 result callback을 분리 합니다.
다시 process와 activity가 재생성 됐을 때 result callback을 사용 할 수 있으려면
사용자 입력 or 비즈로직에 의해 activity 이동이 이루어졌더라도, activity가 (재)생성 될 때 마다 무조건 result callback은 등록이 돼야 합니다.
즉, 실제 액티비티 launch코드가 어느 부분에 쓰이던지간에 result callback은 액티비티 재생성 될 때 무조건 다시 등록 돼야 하므로 callback 등록과 액티비티 launch를 분리시킨 것으로 보입니다
- 1) activity 생성 될 때 무조건 result callback 등록 및 launcher 획득
- 2) 실제 launch(activity 이동) 코드는 원하는 부분에
- 고로 onCreate()/onStart() 내부에서 콜백을 register 해줘야 합니다 -> Activity 생성/재생성 될 때 마다 등록 해야 하므로
*결과 콜백을 액티비티가 started 된 이후 등록하게 되면 아래와 같은 에러를 만나게 됩니다
java.lang.RuntimeException: Unable to resume activity {~~.MainActivity}: java.lang.IllegalStateException: LifecycleOwner ~~.MainActivity@efd3d7a is attempting to register while current state is STARTED. LifecycleOwners must call register before they are STARTED.
# Permission 체크는 어떻게?
val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission(),
ActivityResultCallback { isGranted->
Log.i("syTest", "isGranted : $isGranted")
})
findViewById<TextView>(R.id.checkPermission).setOnClickListener {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)== PackageManager.PERMISSION_GRANTED){
Log.i("syTest", "granted O")
}else{
Log.i("syTest", "granted X")
//launcher실행 - 권한 팝업 뜸
launcher.launch(Manifest.permission.CAMERA)
}
}
# API 바뀐 결과 장점은?
- A -> B Activity 이동 후 다시 A로 돌아 갈 때, A가 destroy 됐다가 재생성 되는 경우에도 Callback을 등록하므로 동작에 문제가 없습니다! (B로 부터 result 값을 받아야 할 경우)
- REQUEST_CODE가 사라졌습니다!! 새로 정의할 무의미한 숫자를 고민하지 않아도 됩니다
- Request가 많아지면서 onActivityResult 분기가 늘어나고 비대해지는 부분도 해결이 되겠습니다
- launch와 result callback의 흐름을 보기가 수월 해졌습니다(보다 유기적으로 연결돼 보입니다)
문제 있을시 알려 주세요.
좋은 하루 되세요!
'Android - 기능' 카테고리의 다른 글
[Android] 바(Bar) 프로그레스 애니메이션 (0) | 2022.03.14 |
---|---|
[Android] 원형(Circle) 프로그레스 애니메이션 (0) | 2022.02.25 |
[Andoird] 카메라 촬영/갤러리 이미지 가져오기 (0) | 2021.11.24 |
[Android] OutLineTextView - 글자 외곽선 더하기 (1) | 2021.11.14 |
[Android] 이미지 공유/Text 공유 (1) | 2021.10.09 |