Activity Result API 사용

21931 단어 AndroidKotlintech
startActivityForResult()에서 또 다른Activity를 호출하고 onActivityResult()에 결과를 받아들이는 코드가 적혀 있는데 이렇게 말하면 새로운 API가 나온다는 생각이 들어서 사용해 봤어요.
  • 활동 결과 얻기 | Android 개발자 | Android Developers
  • startActivityForResult,onActivityResult는 Activity 1.2.0-alpha04에 Deprecated로 되어 있습니다.

    gradle 설정


    위의 문서Activity 1.2.0-alpha02에서 Activity Result API를 가져옵니다.
    현재(2010/09/24)의 최신 버전은 1.20-alpha08이기 때문에build입니다.gradle (: app) 에서 다음과 같습니다.
    dependencies {
        :
        implementation 'androidx.activity:activity-ktx:1.2.0-alpha08'
        implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha08'
        :
    }
    
    처음에는 activity만 썼던 사람도 fragment쓰지 않은 사람도 예외가 발생한다.
  • android - New result API error : Can only use lower 16 bits for requestCode - Stack Overflow
  • 암시적 Intent 처리


    먼저 문서에서 견본으로 쓴 GetContent로 조작해 봅시다.

    처리 결과


    공식 문서에prepareCall()라는 방법이 적혀 있지만 이것1.2.0-alpha04에서는 이름registerForActivityResult()이 바뀐 것 같다.
  • 안드로이드 개발자
  •     private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
            Toast.makeText(this, uri?.toString() ?: "cancelled", Toast.LENGTH_SHORT).show()
        }
    
    uri로만 표시된 Toast 코드.
    선택 취소urinull로 변경됩니다.이해하기 쉬운데.

    호출


    Activity를 시작하는 코드도 작성됩니다.
    이쪽 코드는 공식 문서에도 함수처럼 적혀 있고getContent("image/*"), 이쪽도 1.2.0-alpha05에서 삭제invoke()돼 명확한 호칭launch()이 변경된 것 같다.
  • 안드로이드 개발자
  •         selectButton.setOnClickListener {
                getContent.launch("image/*")
            }
    
    이 몇 줄의 코드로 파일을 선택하는Activity를 시작하고 선택한 파일에 대한 Uri 처리를 적습니다.대단해!간단하네요!

    원래는...


    원래는 아래 코드를 써야 했다.ACTION_GET_CONTENT를 지정하고 억제된 Intent 코드를 투척합니다.이 변화는 정말 사람을 기쁘게 한다.
    const val REQUEST_IMAGE_GET = 1
    
    fun selectImage() {
        val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
            type = "image/*"
        }
        if (intent.resolveActivity(packageManager) != null) {
            startActivityForResult(intent, REQUEST_IMAGE_GET)
        }
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
        if (requestCode == REQUEST_IMAGE_GET && resultCode == Activity.RESULT_OK) {
            val thumbnail: Bitmap = data.getParcelableExtra("data")
            val fullPhotoUri: Uri = data.data
            // Do work with photo saved at fullPhotoUri
            ...
        }
    }
    
    에서 발췌 일반 텐트 | Android 개발자 | Android Developers

    독립적인 Activity 처리


    준비된 동작 이외에 Activity 결과를 처리해야 합니다.
    이 경우 GetContent 대체StartActivityForResult로 통용Intent를 처리할 수 있다.

    Activity 호출


    다음과 같이 Activity를 호출합니다.
    부팅 후 "Result"의 이름으로 결과를 입력하고 돌아오면 됩니다.
    class StringActivity : AppCompatActivity() {
    
        companion object {
            fun createIntent(context: Context): Intent {
                return Intent(context, StringActivity::class.java)
            }
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            setResult(RESULT_OK, Intent().apply {
                putExtra("Result", "success")
            })
        }
    }
    

    처리 결과

    StartActivityForResult로 처리합니다.
    Request Code 분기는 사용되지 않지만 이전에 사용된 코드startActivityForResultonActivityResult 코드와 별 차이가 없는 것 같습니다.
        private val getActivityResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
            if (result.resultCode == RESULT_OK) {
                val string = result.data?.getStringExtra("Result") ?: "empty"
                Toast.makeText(this, string, Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show()
            }
        }
    

    호출


    호출은 호출일 뿐입니다launch().GetContent에서 "image/*"에게 이런 문자열을 주었는데 이것은Intent이다.
                val intent = StringActivity.createIntent(this)
                getActivityResult.launch(intent)
    
    이렇게 하면 일반Intent을 처리할 수 있다.

    좋은 점이 있습니까


    나는 StartActivityForResult로 내가 만든Activity를 처리해 보았지만 늘 좋은 점이 없다고 느꼈다.launch() 낼 수 있어요Intent. 그래서 엇갈릴 수 있어요Intent.
    또 처리 결과도 호출자로서 어떤 데이터를 담았는지 파악해야 한다.
    장래에 사용할 수 없을 때onActivityResult 기계적인 코드 교체라는 인상을 준다.

    새로운 API를 잘 대처해야 돼요.

    StartActivityForResult 처리 결과의 장점도 적다.
    잘 대응하려면 상속GetContentStartActivityForResult의 부류ActivityResultContract를 세운 반이 좋다.

    ActivityResultContract 상속


    방금 제작된StringActivity에서 계승된ActivityResultContract반을 창설했다.
    Android 개발자 | Android Developers GetString I와 O 두 가지 유형의 매개 변수를 취한다.I는 Input이고 O는 Output입니다.
    String Activity에는 Input이 없으므로 IActivityResultContract, Output은 문자열Unit을 반환하려고 합니다.
    다음과 같은 두 가지 방법을 실현한다.
  • String
  • createIntent(context: Context, input: I): Intent
  • Activity를 시작하기 위해 Intent를 반환하는 방법입니다.
    후자는 parseResult(resultCode: Int, intent: Intent?): O에서 처리한 것처럼 진정으로 필요한 데이터를 되돌려주는 방법이다.
        class GetString : ActivityResultContract<Unit, String?>() {
            override fun createIntent(context: Context, input: Unit?): Intent {
                return createIntent(context)
            }
    
            override fun parseResult(resultCode: Int, intent: Intent?): String? {
                return if (resultCode == RESULT_OK) {
                    intent?.getStringExtra("Result")
                } else {
                    null
                }
            }
        }
    
    에서 처리된 코드를String Activity에 가져옵니다.
    호출자는 어떤 데이터가 어떤 키 이름에 저장되는지 파악할 필요가 없다.

    처리 결과

    onActivityResult() 클래스를 만들었기 때문에 호출자는 다음과 같은 코드 처리 결과를 사용할 수 있습니다.
        private val getString = registerForActivityResult(StringActivity.GetString()) { result: String? ->
            Toast.makeText(this, result ?: "Error", Toast.LENGTH_SHORT).show()
        }
    

    호출


    String Activity의 시작도 간단해졌습니다.너무 좋아요!
                getString.launch(Unit)
    

    잡감

    onActivityResult()에 코드를 쓸 때 이 새 API는 "어디가 좋을까요?"이런 의문.
    하지만 각자의 액티비티에 GetString학급을 물려받을 준비를 잘 했다면 지금까지는 어떻게든 액티비티 바깥으로 유출된 물건이 액티비티 안에 잘 갇혀 있어 호출자 코드가 편안해졌다.
    새로운 Activity Result API 좋아요!
    이 코드를 테스트하기 위해서 창고 링크를 붙여 놓으세요.
    https://github.com/t2low/ActivityResultApiSample

    참조 정보

  • 활동 결과 얻기 | Android 개발자 | Android Developers
  • startActivityForesult가 Deprecated로 변하는 대응 방법 - San Builders Blog
  • ActivityResultContract 코드를 살짝 읽어볼게요. - Qita.
  • 좋은 웹페이지 즐겨찾기