0. startActivityForResult() 에 대해 알아보자.( => registerForActivityResult() )

  1. startActivity() : Activity 간의 이동이 이루어지나, 이동전 Activity -> 이동후 Activity. 즉, 단방향으로 작업이 이루어진다.
  2. startActivityForResult(), onActivityResult() : Activity 간의 이동 되는 것은 같으나, 이동후 Activity 로 부터 결과를 받아 올 수 있는 양방향으로 작업이 이루어진다는 점이 다르다.
  • 그러나 웬걸.. 이 API는 이미 deprecated 되었다는 사실!!!
    AndroidX의 androidx.activity:activity:1.2.0 부터는 (startActivityForResult() + onActivityResult()) 대신 registerForActivityResult() 로 사용하도록 안내되어 있다. 두둥! => 자세한 내용은 여기를 Click
  • 개선된 점 : 코드 가독성, REQUEST_CODE 사용 제외, 타입 안정성
  • 사용법이 조금 다르긴 하지만 크게 어렵지 않아 이번 예제에서는 registerForActivityResult() 를 사용해보도록 하자.

 
 

1. 기능 구현

  • MainActivity : SubActivity 로 이동할 Button 1개와 결과값을 받아 보여줄 TextView 를 만들자.
  • SubActivity : SubActivity 를 종료할 Button 1개와 결과값으로 넘겨줄 텍스트를 입력할 EditText 를 만들자.

Flow = MainActivity -> SubActivity : 텍스트 입력 -> SubActivity 종료 -> 입력 텍스트 전달(결과값) -> MainActivity 텍스트 출력

 
 

2. Android Studio에서 기본 프로젝트(with empty activity) 생성하자!

생성시 'Empty Activity'로 기본 생성

 
 

3. ViewBinding 사용을 위한 build.gradle 설정

android {
        // 뷰 바인딩 옵션 활성화
        viewBinding {
            enabled = true
        }
    }

 
 

4. SubActivty.kt, activity_sub.xml 생성하기.

패키지명 우클릭 -> New -> Activity -> Empty Activty : SubActivity 로 이름을 짖자.

 
 

5. activity_main.xml

'GO' Button 1개 + '결과값 출력' TextView 1개

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_comeback"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30sp"
        android:text="값을 가져와 주세요"/>

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/btn_go"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="GO"/>

</LinearLayout>

 
 

6. activity_sub.xml

'종료' Button 1개 + '전달할 결과값 입력' EditText 1개

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SubActivity">

    <EditText
        android:id="@+id/et_comback"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="23sp"
        android:hint="Main으로 보낼 값 입력해주세요"/>

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/btn_close"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="종료"/>

</LinearLayout>

 
 

7. MainActivity.kt

  • openActivityResultLauncher() : registerForActivityResult() 를 사용하여 ActivityResultLauncher 타입을 반환하는 메소드를 만들어 보자.

    registerForActivityResult() 에서는 CallBack 을 등록할뿐, 다른 Activity를 실행하거나 결과 요청을 하지 않는 대신,
    생성,반환된 ActivityResultLauncher 인스턴스를 통해 할 수 있다.
    인스턴스.launch() 를 통해 언제든 다시 결과를 생성하는 프로세스가 시작될 수 있다는 것!

  • 주의할 점

    registerForActivityResult() 를 통한 인스턴스 생성은 Activity 생명 주기 중, onCreate() 또는 onStart() 에서 호출해야한다.
    (만약 onResume() 에서 호출 시, 에러가 발생하니 주의하도록 하자.)

class MainActivity : AppCompatActivity() {

    private var mBinding : ActivityMainBinding? = null
    private val binding get() = mBinding!!

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val activityLauncher= openActivityResultLauncher()

        binding.btnGo.setOnClickListener {
            val intent = Intent(this, SubActivity::class.java)
            activityLauncher.launch(intent)
        }
    }
    private fun openActivityResultLauncher(): ActivityResultLauncher<Intent> {
        val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                result:ActivityResult ->
            if (result.resultCode == Activity.RESULT_OK) {
                Toast.makeText(this, "수신 성공", Toast.LENGTH_SHORT).show()
                binding.tvComeback.text = result.data?.getStringExtra("comeback")
            }
            else {
                Toast.makeText(this, "수신 실패", Toast.LENGTH_SHORT).show()
            }
        }
        return resultLauncher
    }
}

 
 

8. SubActivity.kt

  • intent.putExtra("comeback", binding.etComback.text.toString()) : EditText 값을 Key:comback 으로 하여 Intent 에 넣어보자.
  • setResult(RESULT_OK, intent) : 결과 상태를 OK 로 설정
  • finish() : SubActivity 를 종료하자.
class SubActivity : AppCompatActivity() {

    private var mBinding : ActivitySubBinding? = null
    private val binding get() = mBinding!!

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = ActivitySubBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.btnClose.setOnClickListener {
            val intent = Intent()
            intent.putExtra("comeback", binding.etComback.text.toString())
            setResult(RESULT_OK, intent)
            finish()
        }
    }
}

 
 

9. 실행결과

 
 

10. Reference

유튜버 홍드로이드님의 안드로이드 앱 만들기 #26

  • 주의할 점

    참고한 동영상 강의는 Java 로 진행된 강의입니다. Kotlin 을 공부하기 위한 목적으로 Java-Kotlin 간의 다른 부분에 대해서
    직접 찾아가며 예제 작성을 하였고 영상이 올라온 시점이 3년 전이라 현재의 버전, API 들이 deprecated 된 경우도 있어
    이 또한 현재 권장하는 API로 변경/적용 한 부분이 있어 Code가 다를 수 있으니 보시는 분들은 참고 바람.

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

[Android, Kotlin] BottomNavigation  (0) 2022.04.25
[Android, Kotlin] AndroidX (Jetpack libraries)  (0) 2022.04.25
[Android, Kotlin] BackButton  (0) 2022.04.23
[Android, Kotlin] Spinner  (0) 2022.04.23
[Android, Kotlin] ServiceMusic  (1) 2022.04.22

+ Recent posts