본문 바로가기

내일배움캠프

본 캠프 22일차 - ActivityResultLauncher 또는 register For ResultActivity()

register For ResultActivity()

  • 서로 다른 두 액티비티 간 쌍방향으로 데이터 전달이 가능하게 해주는 것.
class SignInActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sign_in)
        }
}

기존에 메인인 Signin액티비티에서 바로 넣어보았다.

class SignInActivity : AppCompatActivity() {

    private val btid : TextView by lazy { findViewById(R.id.et_id) }
    private val btps : TextView by lazy { findViewById(R.id.et_password) }

    lateinit var activityResultLauncher: ActivityResultLauncher<Intent>

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

우선 초기 화면에서 회원가입 버튼을 눌러서 회원가입 창에서 입력한 내용을 Signin 액티비티로 다시 가져오려고 한다.

처음에는 아무것도 없는 상태니 냅두고 다시 돌아올 때를 가져올 값을 위해 지연초기화를 해준다. 

by lazy lateinit 은 둘 다 지연 초기화로 사용 후 값을 집어 넣는다. 차이점으로는 상수는 앞의 by lazy {}를 사용하고 변수는 lateinit var 를 사용한다.

아이디와 비밀번호를 입력받고 값이 변하지 말아야 하므로 상수를 사용하는 거 같다. lateinit을 집어넣으니 되지 않는다.

변수 이름인 activityResultLauncher는 굳이 저렇게 안써도 되고 : 뒤에 ActivityResultLauncher 만 넣어주고 뒤에 <>안에 인텐트를 넣어주면 된다.

 

이후 onCreate 안에 사용된 변수 activityResultLauncher 에 대해 넣어준다.

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

        val etId = findViewById<EditText>(R.id.et_id)
        val etPass = findViewById<EditText>(R.id.et_password)
        val btn_sign = findViewById<Button>(R.id.btn_sign)

        activityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == RESULT_OK) {
                val id = it.data?.getStringExtra("et_id") ?: ""
                btid.text = id
                val pw = it.data?.getStringExtra("et_pass") ?: ""
                btps.text = pw
            }

        }

activityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) 를 넣어주고 중괄호 열고 result -> 를 넣어도 되고 생략해도 된다. 다만 생략하는 경우 저렇게 it을 사용하고 result ->를 사용하면 그자리에 result를 넣어준다. 코드가 RESULT_OK일때 그것의 데이타가 일단 null이더라도 안전하게 ?를 붙여주고 getStringExtra()를 통해 가져올 코드 이름을 적어넣고 null일 경우 공백으로 남겨두기 위해 ?:"" 를 넣는다.

이제 위에 에딧텍스트 주소를 가져오기 위해 지연초기화 된 상수 btid와 btps를 가져오고 .text로 텍스트를 넣고 이게 id와 pw라고 해둔다. 

 

이제 회원가입창 SignUp 액티비티에 들어가서 put을 해주자.

        btn_ssign.setOnClickListener {
            if (et_name.text.toString().equals("") || et_id.text.toString().equals("") || et_pass.text.toString().equals("")
            ) {
                Toast.makeText(applicationContext, "입력되지 않은 정보가 있습니다.", Toast.LENGTH_SHORT)
                    .show()
            } else {
                Toast.makeText(applicationContext, "가입합니다.", Toast.LENGTH_SHORT).show()
                val intent = Intent(this, SignInActivity::class.java)
                intent.putExtra("et_id", et_id.text.toString())
                intent.putExtra("et_pass", et_pass.text.toString())
			
                setResult(RESULT_OK, intent)
                if (!isFinishing) finish()
                }
	}

 

위에 상수 버튼의 주소를 위해 val btn_ssign을 넣고 그뒤 이것이 눌렸을 때에 대한 것을 넣은 코드이다. (et_name,et_id,et_pass도 같이 만들어 두었다.) || 연산자를 사용하여 셋 중 어느 것 하나라도 빈 칸이 있을 경우 Toast를 통해 알림을 만들었다. 저기서 equals() 는 괄호 안과 같다 라는 연산자 대용으로 사용되는 듯 하다. 따라서 괄호 안에 "" 으로 공백을 넣었기에 공란으로 두면 입력되지 않은 정보가 있다고 뜬다. 

이제 else로 넘어가서 제대로 입력할 경우 가입합니다 라는 문구가 보이게 하고 intetn 함수를 만들어서 메인인 Signin 액티비티로 보낼 준비를 한다. 인텐트 선언 후 putExtra로 "et_id" 라고 이름을 넣었는데 이건 메인에서 getExtra와 이름이 같기만 하면 되는 키값이고, 뒤에 et_id.text로 여기서 호출하는 값이라는 걸 넣어주고 문자이니 .toString() 까지 붙여준다. 비밀번호도 똑같이 만들어준다.

이제 setResult() 를 만들어주고 RESULT_OK이고 인텐트를 하게 해준뒤 finish() 로 회원가입 화면을 꺼주면 된다.

if(!isFinishing) 은 중복 클릭으로 여러번 끄게되면 오류가 발생하므로 끄는중이 아닐때 finish가 되게끔, 즉 안전하게 해주는 문장이다.

 

이제 실행을 해보았는데 오류가 뜨진 않았지만 회원가입창에 입력을 해도 옮겨지지 않고 초기화된 상태로 돌아온다... 대체 왜인지 몰라서 튜터님께 가봤는데 예상보다 너무 간단했다. 

        val btn_join = findViewById<Button>(R.id.btn_join)
        btn_back.setOnClickListener {
            val intent = Intent(this, SignUPActivity::class.java)
            startActivity(intent)
        }

버튼 때문이었다. 회원가입란을 눌렀을 때 문제의 버튼 코드이다.

사실

            val intent = Intent(this,SignUpActivity::class.java)
            activityResultLauncher.launch(intent)

요거를 signin액티비티의 if문 바로 바깥에 넣었는데 이게 아니라 이걸 버튼에 넣었어야 했다.엉뚱한 삽질...

        val btn_join = findViewById<Button>(R.id.btn_join)
        btn_join.setOnClickListener {
            val intent = Intent(this,SignUpActivity::class.java)
            activityResultLauncher.launch(intent)

요렇게 바꾸니 잘 되었다.

다른 부분도 좀 알 수 있었는데

if (et_name.text.toString().equals("") || et_id.text.toString().equals("") || et_pass.text.toString().equals("")
//)

요 부분은 딱 아무것도 입력하지 않은 공란 일 때 만을 위한 문장이었다. 하지만 튜터님이 trim() 과 isEmpty() 를 간단히 알려주셨다.

trim()은 입력할 때 공백이 없게 하는 거고 isEmpty() 는 내가 쓴 equals("") 와 같은 문장이다. 따라서 다시 써보면

 if (et_name.text.toString().trim().isEmpty() || et_id.text.toString().trim().isEmpty() || et_pass.text.toString().trim().isEmpty())

요렇게 바꿀 수 있다.

아직 문법을 제대로 이해하지도 적용하기도 어려운 단계라 .apply 도 간단히 설명 받았다.

else {
       Toast.makeText(applicationContext, "가입합니다.", Toast.LENGTH_SHORT).show()
        val intent = Intent(this, SignInActivity::class.java)
               intent.putExtra("et_id", et_id.text.toString())
               intent.putExtra("et_pass", et_pass.text.toString())

요기 부분에서 여기서는 짧아서 괜찮지만 putExtra를 엄청나게 써야 한다면 intent를 계속 써주는 게 낭비 일 수 있다. 그래서 .apply{}로 자기 자신을 리턴한다고 보면 되는 듯 하다. 이걸 적용해서 코드를 써보면 아래와 같다.

else {
                Toast.makeText(applicationContext, "가입합니다.", Toast.LENGTH_SHORT).show()
                val intent = Intent(this, SignInActivity::class.java).apply {
                    putExtra("et_id", et_id.text.toString())
                    putExtra("et_pass", et_pass.text.toString())
                }

대박이라고 아이디를 만들어주고

가입을 누르면 다시 로그인 창으로 넘어오는데 이제 아이디와 비밀번호가 따라온다

이제 로그인을 누르면

랜덤 이미지 중 하나가 걸렸다. 물론 이름, 나이, 믹스견 이란건 저장 되지 않고 홈액티비티에 저장된 내용이라 좀 그렇지만 일단 아이디는 signin 액티비티에서 받아온 값이다. 이전에 signup 액티비티에서 signin 액티비티로 이번엔 home액티비티까지 아이디를 쭉 값 넘겨주는 게 잘 된 거 같다.

다시 종료를 누르고 처음으로 돌아가서 해보자.

이번엔 다른 아이디와 비번

이거도 종료하지 않고 한건데 잘 따라온다. 다만 아쉬운건 home 액티비티에서 종료를 누르고 초기 화면으로 돌아왔는데 초기화가 되지 않고 회원가입창에서 받았던거 그대로 남아있던게 아쉬운거 같다. 이거 내일 제출 전에 한번 여쭤봐야겠다.

 

뭔가 전부 다는 아니지만 대충 어떤게 들어가야 한다는 건 알 수 있었던 시간이었다.

'내일배움캠프' 카테고리의 다른 글

본 캠프 24일차  (1) 2023.12.21
본 캠프 23일차  (0) 2023.12.20
본 캠프 21일차 - ActivityCompat.finishAffinity  (1) 2023.12.18
본 캠프 20일차 - Intent와 개인과제 시작  (0) 2023.12.15
본 캠프 19일차  (0) 2023.12.14