[안드로이드] registerForActivityResult()

야금야금 공부·2023년 3월 22일

Andriod 이슈사항

목록 보기
1/2

registerForActivityResult()

'인스타그램 클론 프로젝트'를 진행하다가 startActivityForResult()를 더이상 지원하지 않는다는 이슈때문에 다른 함수를 사용했어야 했다.

따라서, startActivityForResult()를 대체할 registerForActivityResult()에 대해 분석해보고자 한다.



startActivityForResult()를 지원하지 않는 이유

  • 기본 startActivityForResult()onActivityResult() API는 모든 API 수준의 Activity 클래스에서 사용 가능하지만, AndroidX Activity와 Fragment에 도입된 Activity Result API 사용을 적극 권장
  • 결과를 얻기 위해 Activity를 시작할 때, 메모리 부족으로 인해 프로세스와 Activity가 소멸될 확률이 높다.
    ex) 카메라 사용

기존 API 방식

startActivityForResult()를 통해 콜백을 등록하고, onActivityResult()에서 콜백을 처리한다.
그러나 이런 방식을 사용했을 때 메모리 부족으로 작업이 소멸할 수 있다.
=> 따라서, 다른 activity를 실행하는 부분에서 콜백을 분리시켜야 한다.

기존 방식으로 구현된 코드

Acitivity로부터 데이터를 전달받기 위해서는 startActivityForResult(Intent, Int) 함수를 이용해 새로운 화면을 호출한다. 그 후, onAcitivityResult(int, int, Intent) 함수로부터 넘어온 데이터를 처리한다.

class OldActivityResultSampleActivity : AppCompatActivity() {
  private val request_second_code = 100

  private fun startSecondView() {
    val intent = Intent(/** context */, ResultSecondActivity::class.java)
    startActivityForResult(intent, request_second_code)    // ◀ Deprecated된 함수
  }
  
  override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)  // ◀ Deprecated된 함수
    if (requestCode == request_second_code) {
      // action to do something
    }
  }
}

registerForActivityResult() API 방식

ActivityResultContractActivityResultCallback을 가져와 다른 activity를 실행하는 데 사용할 ActivityResultLauncher를 반환한다.

새로운 API로 구현된 코드

새로운 표기법에서는 Intent를 작성하는 방법은 동일하지만, 큰 차이점은 startActivityForResult(Intent, int) 함수를 호출하지 않는다는 것이다.

  1. A 액티비티에서 먼저 registerForActivityResult() API를 정의한다.
  2. ActivityResult를 받기 위해 파라미터로 전달하는 ActivityResultCallbackStartActivityForResult 함수를 사용하여 기존 onActivityResult(int, int, Intent) 와 동일한 결과를 처리한다.
    • result 객체를 인자로 받아와 'resultCode'와 'data'에 접근 가능
    • resultCode를 이용해 'RESULT_OK' 인지 확인
    • result.data를 이용해 다른 액티비티에서 보내온 Intent Data를 이용 가능
  3. ActivityResultLauncher을 통해 시작시킨다. 즉, Intent 전달로 새로운 Activity를 호출한다.
  4. B 액티비티에서 데이터를 실어 A 액티비티로 보내주기 위해, setResult() 함수에 resultCodeIntent 데이터를 넣어준다.

import androidx.activity.result.contract.ActivityResultContracts.*

class ActivityResultSampleActivity : AppCompatActivity() {

   val requestActivity: ActivityResultLauncher<Intent> = registerForActivityResult(
        StartActivityForResult()        // ◀ StartActivityForResult 처리를 담당
   ) { activityResult ->
	   // action to do something
   }
  
    private fun startSecondView() {
  
        val intent = Intent(/** context */, ResultSecondActivity::class.java)
        requestActivity.launch(intent)
    }
}
  • 데이터를 보내주기 위한 setResult 함수 사용
secondActivityBtn.setOnClickListener {
    val intent = Intent(this, MainActivity::class.java).apply {
    	putExtra(MainActivity.STRING_INTENT_KEY, "Good")
    }
    setResult(RESULT_OK, intent)
    if (!isFinishing) finish()

ActivityResultCallback으로 전달되는 데이터

  • ActivityResult 타입 데이터를 리턴한다.
  • 각 Request마다 처리를 callback으로 전달해 필요한 결과 부분만 전달
    - 참고 링크 : Pluu Dev
@SuppressLint("BanParcelableUsage")
public final class ActivityResult implements Parcelable {
    private final int mResultCode;
    @Nullable
    private final Intent mData;

    /**
     * Create a new instance
     *
     * @param resultCode status to indicate the success of the operation
     * @param data an intent that carries the result data
     */
    public ActivityResult(int resultCode, @Nullable Intent data) {
        mResultCode = resultCode;
        mData = data;
    }

    ActivityResult(Parcel in) {
        mResultCode = in.readInt();
        mData = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in);
    }



참고 자료

  1. https://developer.android.com/training/basics/intents/result?hl=ko
  2. https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContracts.StartActivityForResult
  3. https://pluu.github.io/blog/android/2020/05/01/migation-activity-result/
  4. https://developer88.tistory.com/351
  5. https://junyoung-developer.tistory.com/151

0개의 댓글