본문 바로가기
개발노트/Kotlin

4주차 4일 과제 리팩토링 및 추가기능구현

by 시계속세상은아직돌아가는중 2023. 8. 3.

1. 리팩토링

    private val id: EditText by lazy { findViewById(R.id.id_create) }
    private val psw: EditText by lazy { findViewById(R.id.psw_create) }
    private val name: EditText by lazy { findViewById(R.id.name_create) }
    private val age: EditText by lazy { findViewById(R.id.age_create) }
    private val gender: EditText by lazy { findViewById(R.id.gender_create) }
    private val mbti: EditText by lazy { findViewById(R.id.mbti_create) }
    private val hobby: EditText by lazy { findViewById(R.id.hobby_create) }

해당 변수들을 다른 함수들에서도 접근할 수 있도록 private함수로 지정해주었다.

 

최초에는 지연초기화를 알지 못하였고, 액티비티의 구동 방식에 대한 이해도가 떨어져 이를 시도할 생각조차 못하였다.

지연 초기화를 사용하지 않은 private 변수는 액티비티를 그림과 동시에 실행되어 오류가 발생하였고

이를 알지 못했던 나는 튜터님께 질문을 통해 답을 얻을 수 있었다.

 

by lazy는 지연을 해주는 구문으로써 이 코드가 사용될 때 해당 동작이 실행되도록 하는 방식이다.

 

   fun Changingcolors(id: View, inputId: String){
        if (inputId.isEmpty()) {
            beRed(id)
        }
    }

기존의 함수의 내용을 줄여서 받을 수 있는 값을 두 개로 바꾸고

            Changingcolors(id, inputId)
            Changingcolors(psw, inputpsw)
            Changingcolors(name, inputname)
            Changingcolors(age, inputage)
            Changingcolors(gender, inputgender)
            Changingcolors(mbti, inputmbti)
            Changingcolors(hobby, inputhobby)

해당 부분을 이런식으로 바꿔주었다.

 

기존에는 위젯이 추가될 때 마다 아래 함수에 일일이 추가하고 또 추가하는 과정을 거쳤어야 했는데, 이러한 형식 변화로 이제는 그냥 이 함수를 불러다가 쓰면 되는 상태다.

 else {
                beRed(id)
                Toast.makeText(this, "중복된 아이디는 생성할 수 없습니다.\n 다시 입력해주세요", Toast.LENGTH_SHORT)
                    .show()
            }

또한 추가 기능을 구현함으로써 beWite가 해당 코드들에서 필요없어졌으므로 삭제하였다.

 

2. 추가기능

 

1) 글자 감지

 fun textInput(id: EditText) {

        id.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

            override fun afterTextChanged(s: Editable?) {
                if (id.text.toString().isNotEmpty()) {
                    beWhite(id)
                }
            }
        })
    }
  @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_signup)

        textInput(id)
        textInput(psw)
        textInput(name)
        textInput(age)
        textInput(gender)
        textInput(mbti)
        textInput(hobby)

    }

이 함수를 사용하기 위해 id값을 가져오는 것을 private 형태로 변경하였다.

 

해당 함수는 EditText의 id를 받아와 해당 텍스트가 변경된 이후에(afterTextChanfed) 작동하는 함수다.

만약 해당 부분이 공백이 아니라면 감지해서 흰색으로 변경되는 함수이다.

 

붉은색으로 변하는건 회원가입 완료 시 공백을 하이라트 해주는 방식이기 때문에 해당 함수에는 넣지 않았다.

 

2)정보전달

resisterForAnctivityResult를 사용해 SignUp 서 SignIn으로 전달한다.

 

            if (UserManager.userList.find { it.id == inputId } == null) {

                UserManager.userList.add(
                    User(
                        inputId,
                        inputpsw,
                        inputname,
                        inputage,
                        inputgender,
                        inputmbti,
                        inputhobby
                    )
                )

                val intent = Intent(this, SignInActivity::class.java)
                intent.putExtra("id", inputId)
                intent.putExtra("psw", inputpsw)
                setResult(Activity.RESULT_OK, intent)
                finish()
            }

완전히 종료되는 시점에서 intent에 저장된 정보를 전달하게 되는데, 로그인 창의 id와 psw를 바로 채워줘서 회원가입 하자마자 해당 아이디와 비밀번호로 로그인을 할 수 있도록 하기 위함이다.

 

이 정보는 SignIn에 있는

 

private val setResultSignup = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val receivedData = result.data

            if (receivedData != null) {
                val receivedId = receivedData.getStringExtra("id")
                val receivedpsw = receivedData.getStringExtra("psw")

                if (receivedId != null) {
                    id.setText(receivedId)
                }

                if (receivedpsw != null) {
                    psw.setText(receivedpsw)
                }
            }
        }
    }

여기에 전달되며, 전달된 정보가 null이 아니라면 전달받은 내용을 텍스트로 띄워준다.

 

이를 구현하면서 텍스트를 어떻게 띄워줄까를 고민하였는데, 변수 내에서 위젯을 접근하는 방식은 옳바른 접근방식은 아니라는 것을 알지만, 일딴은 해당 형식으로 제어해주었다.

 

이를 다시 제대로 구현하는 것이 앞으로의 또 다른 숙제일 것 이다.

 

        signButton.setOnClickListener {
//            val moveToSign = Intent(this, SignupActivity::class.java)
            val intent = Intent(this,SignupActivity::class.java)
            setResultSignup.launch(intent)
//            startActivity(moveToSign)
        }

 

해당 변수는 signButton이 클릭되었을 때 부터 실행하도록 하는 부분이다.

만약 그렇지 않고 처음부터 실행된다면, 여기로 넘어온 정보가 없기 때문에 프로그램 자체가 SignUp액티비티를 먼저 보여줄 것이다. 사실 줄 것이다가 아니라 내가 경험한 것 이다.

 

해당 주석처리된 부분을 까먹고 있다가 에뮬레이터를 동작하는데, SignUp 페이지가 두 개가 겹쳐서 출력되었다.

처음에는 SignUpActivity가 잘못된줄알고 해당 코드들을 디버깅 해보며 보았지만, 아무런 문제가 없었다.

 

튜터님에게 질문한 결과 해당 창이 두 개가 떠오르는 것 같으며 이는 In의 문제임을 찾아낼 수 있었다.

 

여기서 주의해야 했던 것은

 

1. intent는 가급적이면 하나만 쓸 것

2. 각 기능들을 파악하면서 코드를 수정할 것

 

이었다. 생각해보면 intent변수와 moveToSign은 같은 기능을 가진 intent였는데, 아무 생각 없이 블로그를 따라하다가 발생된 오류였다.

 

3)이미지 랜덤

        val img = findViewById<ImageView>(R.id.gundamImg)
        val imageResources = arrayOf(R.drawable.gundam03, R.drawable.gundam05,R.drawable.gundam01)

        var random = Random.nextInt(imageResources.size)
        val randomImg = imageResources[random]


        img.setImageResource(randomImg)

1. 먼저 이미지뷰의 id를 가져온다

2. 이미지들을 전부 배열의 형태로 저장한다.

3. 랜덤변수를 만든다.

4. 랜덤변수를 setImage에 넣으면 쨔잔! 무작위 이미지가 나온다.

 

최초 아이디어는 이러했다.

 

draw해줘야 하는 부분이

 

drawable/gundam1

 

일 때 drawable/gundamx

 

x = random변수이며 사진의 갯수만큼 변동된다

 

로 최초에 생각했으나, 그럴려면 애초에 사진의 갯수를 구해야하고

그 방법은 해당 배열을 만든 뒤 배열의 사이즈를 구해야하는 방식으로 귀결되었다.

 

따라서 제목에 접근하는 방식은 배제하고 이미지의 배열 중 랜덤하게 접근하도록 구성하였다.

 

참고 블로그

지연초기화에 대해

https://jerryjerryjerry.tistory.com/85

 

[Kotlin] 코틀린 lateinit, lazy로 늦은 초기화, 초기화 지연

개발을 하다보면 변수를 선언할때 초기에 값이나 상태를 정의하기 어려워 null로 선언하는 경우나, 필요한 시점에 초기화를 해야하는 경우가 있을것 이다. 자바와 같은 고전적인 언어들은 변수

jerryjerryjerry.tistory.com

 

 

addTextChangedListener,textWatcher

 

https://blog.naver.com/moonysl/140148993163

 

문자열 변경 이벤트

EditText ...

blog.naver.com

https://yeo0616.tistory.com/205#TextWatcher%--%EC%--%AC%EC%-A%A-%EB%B-%---feat-addTextChangedListener-

https://itstudy-mary.tistory.com/344

 

Android Studio, Kotlin] 2. addOnTextChangeListener. EditText가 변경될 때 마다 이벤트를 발생시키는 함수

다음 코드를 보면 화면에 입력된 숫자에 따라 RGB 코드를 받아 view 색이 변경되는 것을 볼 수 있다. 이것을 적용시키려면, 텍스트가 변경될 때마다 색상을 변화시켜야 하는데, 이를 도와주는 리스

itstudy-mary.tistory.com

 

registerForActivityResult

https://velog.io/@ho-taek/Android-registerForActivityResult%EB%9E%80

 

[Android] registerForActivityResult()란?

! 기존에 데이터 주고 받을 때 사용했던 startActivityForResult()가 derpecated 됐고, 다른 방법을 찾아보다가 registerForActivityResult()에 대해 알게 되었다!! 그 사용법에 대해 간단하게 알아보자 <img src =h

velog.io

 

https://velog.io/@soyoung-dev/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%EC%BD%94%ED%8B%80%EB%A6%B0-registerForActivityResult-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

[Android/Kotlin] registerForActivityResult() 사용하기

기존에는 액티비티에서 결과를 받아올 때 startActivityForResult() 와 onActivityResult() 를 사용했지만 deprecated 되었다Activity 클래스에서 사용할 수 있지만, AndroidX Activity와 Fragment에 도입된

velog.io

 

https://developer88.tistory.com/351

https://developer.android.com/training/basics/intents/result?hl=ko#custom

 

활동에서 결과 가져오기  |  Android 개발자  |  Android Developers

활동에서 결과 가져오기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 앱 내에서든 다른 앱에서든 다른 활동을 시작하는 것은 단방향 작업이 아니어도 됩

developer.android.com

오늘 푼 문제

https://clockstillticktockticktock.tistory.com/33

 

프로그래머스 머쓱이보다 큰 사람 코틀린

https://school.programmers.co.kr/learn/courses/30/lessons/120585 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞

clockstillticktockticktock.tistory.com

https://clockstillticktockticktock.tistory.com/32

 

프로그래머스 문자 정렬하기(2) 코틀린

https://school.programmers.co.kr/learn/courses/30/lessons/120911 프로그래머스 코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞

clockstillticktockticktock.tistory.com