Archives
Recent Posts
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Today
Total
관리 메뉴

안드로이드 개발자의 창고

[34일차 Android] OnActivityResult 본문

Computer/Android

[34일차 Android] OnActivityResult

Wise-99 2023. 6. 23. 01:28

 

 

 

출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 PPT

 

 

 

📖 startActivityForResult

  • Activity에서 다른 Activity를 실행하고 다시 돌아왔을 때 어떤 처리가 필요하다면 Activity를 실행할 때 startActivity가 아닌startActivityForResult 메서드를 사용한다.

onActivityResult

  • startActivityForResult 메서드를 이용해 Activity를 실행하고 돌아오면 자동으로 onActivityResult 메서드가 호출된다.
  • 여기에서 필요한 작업을 처리한다.

 

 

 

예제 코드

MainActivity.kt - startActivityForResult()

button.run {
    setOnClickListener {
        // SecondActivity 실행
        val secondIntent = Intent(this@MainActivity, SecondActivity::class.java)
        // startActivity(secondIntent)

        // 값들을 설정한다.
        secondIntent.putExtra("data1", 100)
        secondIntent.putExtra("data2", 11.11)
        secondIntent.putExtra("data3", true)
        secondIntent.putExtra("data4", "안녕하세요")

        val t1 = TestClass()
        t1.name = "홍길동"
        t1.age = 100
        secondIntent.putExtra("data5", t1)

        // requestCode - 개발자를 위한 코드
        startActivityForResult(secondIntent,SECOND_ACTIVITY)
    }
}
  • startActivityForResult로 Activity를 전환하는 코드이다.
  • secondIntent를 선언하여 MainActivity에서 SecondActivity로 전환하도록 한다.
  • secondIntent에 data1~4와 TestClass()의 객체를 전달한다.
  • SECOND_ACTIVITY는 requsetCode로 개발자가 Activity를 구분하기 위해 사용한다.

 

MainActivity.kt - onActivityResult()

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when(requestCode){
            SECOND_ACTIVITY -> {
                activityMainBinding.textView.text = "SecondActivity에서 돌아왔습니다\n"
                // resultCode로 작업의 결과를 구분한다.
                when(resultCode){
                    RESULT_OK -> {
                        activityMainBinding.textView.append("작업 성공\n")
                        // 3번째 매개변수로 전달되는 Intent 객체로부터 데이터를 추출해 사용한다.
                        if (data != null){
                            val value1 = data.getIntExtra("value1", 0)
                            val value2 = data.getDoubleExtra("value2", 0.0)
                            val value3 = data.getBooleanExtra("value3", false)
                            val value4 = data.getStringExtra("value4")

                            activityMainBinding.textView.append("value1 : ${value1}\n")
                            activityMainBinding.textView.append("value2 : ${value2}\n")
                            activityMainBinding.textView.append("value3 : ${value3}\n")
                            activityMainBinding.textView.append("value4 : ${value4}\n")
                        }
                    }
                    RESULT_CANCELED -> {
                        activityMainBinding.textView.append("작업 취소\n")
                    }
                }
            }
            THIRD_ACTIVITY -> {
                activityMainBinding.textView.text = "ThirdActivity에서 돌아왔습니다\n"
            }
        }
    }
  • startActivityForResult()에 전달한 requsetCode로 각각의 Activity를 구분한다.
  • setResult()로 전달된 작업 결과로 한 번 더 분기 처리를 한다.

 

MainActivity.kt - TestClass()

class TestClass() : Parcelable{

    lateinit var name : String
    var age:Int = 0

    // 객체를 Intent에 저장하면 parcel에 저장됨
    constructor(parcel: Parcel) : this() {
        // 멤버 변수에 값을 담는다.
        // Parcel에 저장한 순서대로 추출한다.
        name = parcel.readString()!!
        age = parcel.readInt()
    }

    // 객체를 Intent에 넣으려고 할 때 호출된다.
    // 매개 변수로 전달되는 parcel 객체에 객체 복원에 필요한 값들을 넣어준다.
    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(name)
        parcel.writeInt(age)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<TestClass> {
        // Intent로 부터 객체를 추출할 때 호출되는 메서드
        // 새로운 객체를 생성하고 parcel에 저장되어 있는 값을 객체 맴버 변수에 담아준다.
        override fun createFromParcel(parcel: Parcel): TestClass {
            return TestClass(parcel)
        }

        override fun newArray(size: Int): Array<TestClass?> {
            return arrayOfNulls(size)
        }
    }
}
  • 안드로이드에서 4대 구성요소 간에 객체를 전달하기 위한 직렬화를 수행하기 위해 Parcelable 인터페이스를 구현한다.
  • Java의 Serialize와 같은 역할을 한다.

 

SecondActivity.kt

secondBinding.run {
            // Activity를 실행하기 위해 사용한 Intent로부터 데이터를 추출한다.
            textViewSecond.text = "SecondActivity\n"

            // 기본 자료형에 관련된 메서드들을 데이터의 이름과 저장된 것이 없을 경우 사용할 기본 값을 설정한다.
            val data1 = intent.getIntExtra("data1", 0)
            val data2 = intent.getDoubleExtra("data2",0.0)
            val data3 = intent.getBooleanExtra("data3", false)
            // 객체는 기본값을 설정하지 않으며 값이 없을 경우에는 null이 반한된다.
            val data4 = intent.getStringExtra("data4")

            textViewSecond.append("data1 : ${data1}\n")
            textViewSecond.append("data1 : ${data2}\n")
            textViewSecond.append("data1 : ${data3}\n")
            textViewSecond.append("data1 : ${data4}\n")

            // 객체를 복원한다.
            // SDK 버전별 처리
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){
                val data5 = intent.getParcelableExtra("data5", TestClass::class.java)
                textViewSecond.append("data5.name : ${data5?.name}")
                textViewSecond.append("data5.age : ${data5?.age}")
            } else {
                val data5 = intent.getParcelableExtra<TestClass>("data5")
                textViewSecond.append("data5.name : ${data5?.name}")
                textViewSecond.append("data5.age : ${data5?.age}")
            }

            buttonSecond.run {
                setOnClickListener {
                    // 작업의 결과를 설정해준다.
                    // RESULT_OK : 작업이 정상적으로 끝났다는 것을 의미한다.
                    // RESULT_CANCELED : 작업이 취소되었다는 것을 의미한다.
                    // RESULT_FIRST_USER : 작업의 상황을 더 추가적으로 정의하고 싶을 때(+1, +2, +3...)
                    // setResult(RESULT_OK)
                    // setResult(RESULT_CANCELED)

                    // 이전 Activity로 전달할 데이터를 설정할 Intent 객체를 생성한다.
                    val resultIntent = Intent()
                    // 값을 설정한다.
                    resultIntent.putExtra("value1", 200)
                    resultIntent.putExtra("value2", 22.22)
                    resultIntent.putExtra("value3", false)
                    resultIntent.putExtra("value4" , "반갑습니다")

                    // 돌아갈 때 전달할 값이 있다면
                    // setResult 메서드의 두번째 매개 변수에 Intent 객체를 넣어준다.
                    setResult(RESULT_OK, resultIntent)

                    // Activity 종료
                    finish()
                }
            }
        }
  • SecondActivity에서 button을 클릭했을 때 실행되는 코드
  • SDK 버전별로 객체를 복원하는 메서드가 다르다.
  • setResult()로 작업의 결과와 Intent를 전달한다.

📖 registerForActivityResult

  • startActivityForResult 와 onActivityResult 메서드 조합 대신 사용한다.
  • 다수의 액티비티 실행을 분리해 관리할 수 있다는 장점을 가지고 있다.

 

 

 

예제 코드

MainActivity.kt - onCreate() 내부

val c1 = ActivityResultContracts.StartActivityForResult()
val fourthActivityLauncher = registerForActivityResult(c1){
    
    // FourthActivity를 갔다 돌아왔을 때의 코드를 구현한다.
    textView.text = "FourthActivity를 갔다 돌아왔습니다\n"

    // Result Code로 분기한다.
    if (it.resultCode == RESULT_OK){
        // Intent를 통해 값들을 추출한다.
        val value1 = it.data?.getIntExtra("value1", 0)
        val value2 = it.data?.getDoubleExtra("value2", 0.0)

        textView.append("value1 : ${value1}\n")
        textView.append("value2 : $value2")
    }
}
  • registerForActivityResult()를 사용한 코드
  • ActivityResultContracts를 사용하여 계약 객체(c1)을 생성한다.
  • 계약 객체는 '이 객체를 가지고 ~~를 할거다'라는 의미이다.
  • 이 코드는 다른 Activity를 갔다 돌아왔을 경우라는 것을 의미하는 StartActivityForResult()를 사용한다.

 

button3.run {
    setOnClickListener {
        // FourthActivity 실행
        val fourthIntent = Intent(this@MainActivity, FourthActivity::class.java)

        fourthIntent.putExtra("data1", 100)
        fourthIntent.putExtra("data2", 11.11)

        fourthActivityLauncher.launch(fourthIntent)
    }
}
  • 위에서 선언한 fourthActivityLauncher를 사용하여 Intent를 전달한다.

'Computer > Android' 카테고리의 다른 글

[37일차 Android] Toast  (0) 2023.06.23
[37일차 Android] 다른 앱의 Activity 실행하기  (0) 2023.06.23
[34일차 Android] Activity 실행하기  (0) 2023.06.17
[34일차 Android] Activity  (0) 2023.06.17
[34일차 Android] Popup Menu  (0) 2023.06.17