이번엔 '리턴을 받는 요청' 에 대해 알아보자.
MainActivity에서 Activity2로 Intent를 통해 두 수를 전달하고, 두 수를 더한 값을 다시 MainActivity로 전달 받을 것이다.
실습을 위해 아래와 같이 MainActivity와 Activity2를 구성한다.
[MainActivity]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="154dp"
android:layout_marginTop="148dp"
android:layout_marginEnd="166dp"
android:layout_marginBottom="535dp"
android:text="1+2는?"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/txt_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="176dp"
android:layout_marginTop="47dp"
android:layout_marginEnd="177dp"
android:textSize="20dp"
android:textStyle="bold"
android:text="정답이 뭘까요?"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />
</androidx.constraintlayout.widget.ConstraintLayout>
[Activity2]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".Activity2">
<TextView
android:id="@+id/txt_answer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40dp"
android:text="Answer"/>
<Button
android:id="@+id/btn_return"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="값 전달" />
</LinearLayout>
기존에 요청에 대한 값을 전달받기 위해선 startActivityForResult() 함수를 통해 intent를 시스템에 요청하고, onActivityResult()를 override하여 값을 얻어왔지만, 현재 startActivityForResult()는 보안상의 이유로 deprecated되었다.
그렇기 때문에 startActivityFroResult() 대신에 ActivityResultLauncher를 사용하여 요청과 결과를 유형별로 관리한다.
ActivityResultLauncher에 대한 설명은 gpt 4.0의 답변으로 대신한다.
ActivityResultLauncher는 registerForActivityResult() 메서드에 의해 반환되는 인스턴스입니다. 이 인스턴스는 요청을 시작하고 결과를 처리하는데 사용됩니다.
registerForActivityResult()는 ActivityResultContract와 ActivityResultCallback을 인자로 받습니다.
- ActivityResultContract: 요청과 응답의 유형을 정의합니다. Android에는 기본 제공된 몇 가지 contracts가 있습니다. 예를 들어, ActivityResultContracts.StartActivityForResult는 Intent를 입력으로 사용하고, ActivityResult를 결과로 반환합니다.
- ActivityResultCallback: 결과를 처리하기 위한 콜백입니다.
val exampleLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
// handle the result
}
}
// To launch the activity
exampleLauncher.launch(Intent(this, ExampleActivity::class.java))
예를 들어, 다음 코드는 ActivityResultContracts.StartActivityForResult contract를 사용하여 Activity를 시작하고 결과를 처리합니다.
위의 예제에서, exampleLauncher는 ActivityResultLauncher 인스턴스입니다. 이 인스턴스의 launch 메서드는 ExampleActivity를 시작합니다. ExampleActivity가 종료되면 ActivityResultCallback의 onActivityResult 메서드가 호출됩니다. ActivityResult는 resultCode 및 data를 포함합니다.
ActivityResultLauncher를 사용하면 startActivityForResult() 및 onActivityResult() 메서드를 사용하지 않아도 됩니다. ActivityResultLauncher는 이러한 메서드의 최신 대안입니다.
실습을 위해 MainActivity에 ActivityResultLauncher를 생성하여 아래와 같이 사용한다.
[MainActivity.kt]
package com.example.androidstudy
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) //화면을 그려주는 부분(해당 레이아웃으로 화면을그려주겠다)
var changeActivity : Button = findViewById(R.id.button) //activity2로 넘어가기 위한 버튼
var resultText : TextView = findViewById(R.id.txt_result) //정답을 보여주기 위한 text
//startActivityForResult => deprecated됨, 따라서 ActivityResultLauncher를 사용하여 요청을 정리
//요청에 대한 응답을 수행하기 위한 ActivityResultLauncher객체 정의
val activity2Launcher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == RESULT_OK) {
//result의 data로부터 activity2에서 전달한 intent의 키워드 sum에서 정보 얻어오기
val sum = result.data?.getIntExtra("SUM", 0)
resultText.text = sum.toString()
}
}
//Intent에 정보 담아서 보내기
changeActivity.setOnClickListener{
val intent = Intent(this@MainActivity,Activity2::class.java)
intent.apply {
this.putExtra("number1",1) // "number1" : 1 형태로 값 담기
this.putExtra("number2",2) // "number2" : 2 형태로 값 담기
}
//activity2Launcher의 launch로 intent 넘겨주기 : 해당 Intent의 결과값을 activity2Launcher에서 수행
activity2Launcher.launch(intent) //리턴을 받는 요청 보내기 startActivityForResult => deprecated
}
}
}
위 코드에서는 Activity2로부터 sum이라는 키워드로 integer값을 전달받으면 resultCode를 확인하고, 정상적으로 전달 받았다면 텍스트뷰의 값을 변경하도록 하였다.
ActivityResultLaunch에는 intent의 응답에 대한 정의가 되어 있으므로 생성한 activity2Launcher의 launch함수로 intent를 매개변수로 넣어 시스템에 intent를 요청한다.
Activity2에서는 전달받은 두 숫자를 더해서 MainActivity로 전달할 것이다. 버튼을 눌렀을때 두 수의 합을 sum이라는 키워드로 전달하도록 한다.
package com.example.androidstudy
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class Activity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_2)
//값 꺼내기 : number1, number2라는 키 값이 없을 수 있으므로 예외 처리 필요
val number1 = intent.getIntExtra("number1",0)
val number2 = intent.getIntExtra("number2",0)
var answer : TextView = findViewById(R.id.txt_answer)
answer.text = " 1 + 2 = " + (number1+number2).toString()
var sum = number1 + number2
val returnButton : Button = findViewById(R.id.btn_return)
//버튼 클릭시 MainActivity로 값 전달하기
returnButton.setOnClickListener{
//결과값 전달하기(해당 Activity에서 제대로 값을 전달받았다는 의미로)
var resultIntent = Intent() //결과값을 전달하기 위한 인텐트 생성
resultIntent.putExtra("SUM", sum)
setResult(RESULT_OK, resultIntent) //RESULT_OK는 -1과 같음, 값을 제대로 전달받았다는 의미
finish() //스택에서 activity2제거
}
}
}
결과값을 전달하기 위해서도 마찬가지로 Intent객체가 필요하며, setResult()함수를 통해 resultCode와 Intent를 매개변수로 넘겨 MainActivity의 ActivityReusltLauncher에서 확인 할 수 있도록 한다.
이후 activity2를 스택에서 제거함으로서 화면에서 더이상 보이지 않도록 한다.
영상을 통해 결과를 확인해보자.