연습장/실습

3주차_ 소개글 앱 4. registerForActivityResult

아이른 2024. 3. 21. 21:05

문제Lv4.

  • 회원 가입 페이지에서 입력한 아이디/비밀번호가 회원 가입 버튼을 눌러 로그인 화면으로 이동할 때 자동으로 입력되도록 구현합니다.
  • Hint : registerForActivityResult 를 알아봅시다.

1. Activity Result API?

  • 앱 내에서 활동을 시작하고 활동에서 얻은 결과를 받을 수 있음
  • Activity Result API는 시스템에서 결과가 전달되면 이를 등록, 실행, 처리하기 위한 구성요소를 제공

API란 무엇인가요? - 애플리케이션 프로그래밍 인터페이스 설명 - AWS (amazon.com)

 

API란 무엇인가요? - 애플리케이션 프로그래밍 인터페이스 설명 - AWS

GraphQL은 API용으로 특별히 개발된 쿼리 언어로서, 클라이언트에게 요청한 데이터만 제공하는 것을 우선으로 합니다. 또한 API를 빠르고 유연하며 개발자 친화적으로 만들도록 설계되었습니다. RES

aws.amazon.com

  • 메모리 이슈로 Activity Result API는 다른 활동을 실행하는 코드 위치에서 콜백을 분리

 

2. registerForActivityResult

  • Activity 또는 Fragment에 있을 때, Activity Result API에서 제공하는 registerForActivityResult() API를 통해 결과 콜백 등록 가능
  • registerForActivityResult()는 ActivityResultContract 및 ActivityResultCallback 가져와서 다른 Activity를 실행하는 데 사용할 ActivityResultLauncher를 반환
  • ActivityResultContract : 결과를 생성하는 데 필요한 입력 유형과 결과의 출력 유형을 정의
  • ActivityResultCallback : ActivityResultContract에 정의된 출력 유형의 객체를 가져오는 onActivityResult() 메서드가 포함된 단일 메서드 인터페이스
  • ActivityResultLauncher : 활동 결과 실행기

 

2-1. registerForActivityResult 사용법

  • 수신하는 엑티비티 : 회원가입 정보 결과를 받는 로그인 화면 = SignInActivity
    • ActivityResult를 받고자 하는 엑티비티에 Callback 등록

①  ActivityResultLauncher 라는 타입의 resultLauncher 변수 선언

private lateinit var resultLauncher: ActivityResultLauncher<Intent>
//private : 클래스 내부에서만 접근 (접근 제한자)
//lateinit : var로 선언하여 늦은 초기화 이후에도 계속 값 변경 가능 (지연초기화)
//var resultLauncher : resultLauncher는 변수명이기에 다른 명 사용 가능 (변수)
//ActivityResultLauncher : ActivityResultLauncher라는 타입의 변수 선언 (타입, 자료형)
//<Intent> : 값는 받는 Intent 안에서 사용을 제한 (제너릭)

 

② resultLauncher 변수에 registerForActivityResult() 활용

resultLauncher =
	registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
//ActivityResultContracts : 결과를 생성하는 데 필요한 입력 유형과 결과의 출력 유형을 정의
//StartActivityForResult() : 새 액티비티를 열어줌 + 결과값 전달 (쌍방향)
//회원가입 엑티비티에서 결과 값을 받아올 수 있는 구문

	if (result.resultCode == RESULT_OK) {
//resultCode : 여러 화면의 이동을 가정할 때, 데이터도 함께 이동하는데 이를 구분하기 위해 사용하는 코드
//RESULT_OK : 기본 값
//RESULT_OK에 전달받은 ActivityResult 수신 구문이 조건문과 같을 때 실행

		val id = result.data?.getStringExtra("id") ?: ""
//getStringExtra("id") 혹은 ""
//getExtra() : 여러가지 타입의 값이 들어가기 때문에 getStringExtra() 사용
//data : getStringExtra("id") ?: "" 을 통틀어서 data로 지정 = bundle과 같은 개념
		val pw = result.data?.getStringExtra("pw") ?: ""

			et_id.setText(id)
			et_pw.setText(pw)
	}
}

 

③ 변수 resultLauncher.launch()를 통해 데이터를 받아올 Acitivity를 실행

btn_signUp.setOnClickListener {
	val intent = Intent(this, SignUpActivity::class.java)
	resultLauncher.launch(intent)
//startActivityResult랑 동일한 기능
}

 

④ SignInActivity.kt

class SignInActivity : AppCompatActivity() {
    private lateinit var resultLauncher: ActivityResultLauncher<Intent>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val btn = findViewById<Button>(R.id.btn_login)
        val btn_signUp = findViewById<Button>(R.id.btn_signup)
        val et_id = findViewById<EditText>(R.id.et_id)
        val et_pw = findViewById<EditText>(R.id.et_pw)

        btn.setOnClickListener {

            if (et_id.text.isEmpty()) {
                Toast.makeText(this, "아이디를 입력해주세요", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            if (et_pw.text.isEmpty()) {
                Toast.makeText(this, "비밀번호를 입력해주세요", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }

            Toast.makeText(this, "로그인 성공", Toast.LENGTH_SHORT).show()

            val strData = et_id.text.toString()
            val intent = Intent(this, HomrActivity::class.java)
            intent.putExtra("login", strData)
            startActivity(intent)
        }

        btn_signUp.setOnClickListener {
            val intent = Intent(this, SignUpActivity::class.java)
            resultLauncher.launch(intent)
        }

        resultLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == RESULT_OK) {
                    val id = result.data?.getStringExtra("id") ?: ""
                    val pw = result.data?.getStringExtra("pw") ?: ""

                    et_id.setText(id)
                    et_pw.setText(pw)
                }
            }
    }
}
  • 데이터를 전달하는 엑티비티 : 회원가입 화면 = SignUpActivity
    • ActivityResuit를 전달하는 엑티비티에 setResult 등록
class SignUpActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sign_up)

        val btn = findViewById<Button>(R.id.btn_login)

        btn.setOnClickListener {

            val et_name = findViewById<EditText>(R.id.et_name)
            val strName = et_name.text.toString()
            val et_id = findViewById<EditText>(R.id.et_id)
            val strId = et_id.text.toString()
            val et_pw = findViewById<EditText>(R.id.et_pw)
            val strPw = et_pw.text.toString()

            val isName = strName.isEmpty()
            val isId = strId.isEmpty()
            val isPw = strPw.isEmpty()

            if (isName || isId || isPw){
                Toast.makeText(this, "입력되지 않은 정보가 있습니다", Toast.LENGTH_SHORT).show()
            }else{
                intent.putExtra("id",strId)
                intent.putExtra("pw",strPw)
                setResult(RESULT_OK, intent)
                //RESULT_OK : -1 값을 RESULT_OK로 받는 것
                //setResult : 값을 넘겨주는 역할
                finish()
            }
        }
    }
}

동작화면

회원가입 화면 로그인 화면으로 이동할 때 자동으로 값 입력