안드로이드 개발을 진행하다 보면 단순히 액티비티를 전환하고 끝! 이 아니라
이후 발생한 액티비티에서 작업을 하고 원래 액티비티에 돌아와서 사용하고 싶은 경우가 있습니다.
이럴때 이전까진 startActivityForResult()와 onActivityResult() 함수를 사용해서 처리해 주곤 했습니다. 그렇지만, 이미 onActivityResult는 Deprecated 된 함수입니다.
최근엔 새로운 Activity Result API 사용을 권장하고 있습니다. 다양한 Activity Result API 중 Activity 간의 Result 처리에는 ActivityResultContracts.StartActivityForResult를 사용해야 합니다.
오늘은 간단한 예제를 통해 전환된 액티비티에서 작업한 데이터를 받아오는 작업을 해보겠습니다.
다음은 전체 코드 입니다.
activity_test_activity_result.xml
<?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=".ActivityTestActivityResult">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="화면 이동"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.897" />
<TextView
android:id="@+id/data_TV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="받은값 없음"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sendData_ET" />
<EditText
android:id="@+id/sendData_ET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="text"
android:text="보낼 데이터"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_get_data.xml
<?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=".ActivityGetData">
<EditText
android:id="@+id/getData_ET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="받은 데이터"
android:inputType="text"
app:layout_constraintBottom_toTopOf="@+id/text_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="데이터를 수정하고 확인을 눌러주세요"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.367" />
<Button
android:id="@+id/submit_BTN"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="확인"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
ActivityTestActivityResult.kt
package com.example.stickcodepost
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.example.stickcodepost.databinding.ActivityTestActivityResultBinding
class ActivityTestActivityResult : AppCompatActivity() {
// ActivityResultLauncher 인스턴스를 선언합니다.
private lateinit var getResult: ActivityResultLauncher<Intent>
// 전역 변수로 바인딩 객체 선언
private var mBinding: ActivityTestActivityResultBinding? = null
// 매번 null 체크를 할 필요 없이 편의성을 위해 바인딩 변수 재 선언
private val binding get() = mBinding!!
// !!는 Kotlin에서 Nullable 타입을 강제로 Non-nullable 타입으로 변환하는 것을 의미
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 자동 생성된 뷰 바인딩 클래스에서의 inflate라는 메서드를 활용해서
// 액티비티에서 사용할 바인딩 클래스의 인스턴스 생성
mBinding = ActivityTestActivityResultBinding.inflate(layoutInflater)
// getRoot 메서드로 레이아웃 내부의 최상위 위치 뷰의
// 인스턴스를 활용하여 생성된 뷰를 액티비티에 표시합니다.
setContentView(binding.root)
// ActivityResultLauncher를 초기화합니다.
getResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
// 결과 처리 콜백 함수입니다.
if (result.resultCode == RESULT_OK) {
// 결과가 OK일 경우 처리합니다.
val getData = result.data?.getStringExtra("returnValue")
// 화면에 결과 데이터를 표시합니다.
binding.dataTV.text = getData
}
}
// 버튼 클릭 리스너를 설정합니다.
binding.button.setOnClickListener {
val strData = binding.sendDataET.text.toString()
val mIntent = Intent(getApplicationContext(), ActivityGetData::class.java)
// 입력한 데이터를 인텐트에 추가합니다.
mIntent.putExtra("strData", strData)
// getResult를 사용하여 다른 액티비티를 실행하고 그 결과를 처리합니다.
getResult.launch(mIntent)
}
}
}
ActivityResultLauncher 객체를 이용해서 Callback 함수를 만들어 줍니다.
예제에선 결과값을 result 에 담았습니다.
해당 콜백 함수의 result 를 체크해서 RESULT_OK 값을 체크해주고
result.data? 에서 결과값을 받아올 수 있습니다.
예제의 경우 getStringExtra 로 결과값을 받아오도록 했습니다.
만들어진 Callback 함수를 이용해 Intent 를 실행시켜 줍니다.
ActivityGetData.kt
package com.example.stickcodepost
import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.stickcodepost.databinding.ActivityGetDataBinding
class ActivityGetData : AppCompatActivity() {
// 전역 변수로 바인딩 객체 선언
private var mBinding: ActivityGetDataBinding? = null
// 매번 null 체크를 할 필요 없이 편의성을 위해 바인딩 변수 재 선언
private val binding get() = mBinding!!
// !!는 Kotlin에서 Nullable 타입을 강제로 Non-nullable 타입으로 변환하는 것을 의미
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 자동 생성된 뷰 바인딩 클래스에서의 inflate라는 메서드를 활용해서
// 액티비티에서 사용할 바인딩 클래스의 인스턴스 생성
mBinding = ActivityGetDataBinding.inflate(layoutInflater)
// getRoot 메서드로 레이아웃 내부의 최상위 위치 뷰의
// 인스턴스를 활용하여 생성된 뷰를 액티비티에 표시합니다.
setContentView(binding.root) // < 기존의 setContentView는 주석 처리해 주세요!
// 인텐트로부터 전달된 데이터를 가져옵니다.
val strData = intent.getStringExtra("strData")
// 가져온 데이터를 EditText에 설정합니다.
binding.getDataET.setText(strData.orEmpty())
// 리스너 초기화 메서드를 호출합니다.
initListener()
}
private fun initListener() {
// 버튼 클릭 리스너를 초기화합니다.
binding.submitBTN.setOnClickListener {
// 결과를 담을 인텐트를 생성합니다.
val intent = Intent()
// EditText에서 데이터를 가져와서 인텐트에 추가합니다.
val data = binding.getDataET.text.toString()
intent.putExtra("returnValue", data)
// 결과 코드와 인텐트를 설정하고 현재 액티비티를 종료합니다.
setResult(Activity.RESULT_OK, intent)
finish()
}
}
}
이동한 액티비티 에서 변경된 데이터를 돌려 줄때 성공여부에 대해 setResult() 에서 첫번째 파라미터 값이 값 을 주면 원래 액티비티에서 돌아갔을때 해당 값을 처리해줄 수 있습니다.
예제를 실행시켜 보겠습니다.
최초에 testData 를 작성해서 다음 액티비티로 보내줍니다.
이동한 액티비티에서 받은 testData 를 modifydata 로 변경해주고 확인 버튼을 누르면 본래 Activity 로 돌아오고
변경 된 값을 받아온것을 볼 수 있습니다.
'안드로이드 코틀린' 카테고리의 다른 글
[Android][kotlin] youtubePlayer 라이브러리 를 이용해 유튜브영상 표시해 주기 (2) | 2023.10.01 |
---|---|
[Kotlin][Android]Gson 이용해서 Json 데이터 다루기 (0) | 2023.09.11 |
[Kotlin][Android] View Model에서 안드로이드 문자열 관리하기 (0) | 2023.02.06 |
[Kotlin][Android] StartActivityForResult 대신 RegisterActivityForResult 사용하기 (0) | 2023.01.17 |
[Kotlin][Android] Camposer: Jetpack Compose 카메라 라이브러리 사용하기 (0) | 2023.01.05 |