[24.06.21] TIL - 016

0. 오늘은 무엇을 했는가

오늘은 벌써 금요일입니다.

오늘은 코드 카타를 풀고, 개인 과제를 마무리했습니다.

그리고, 코틀린과 안드로이드 공부를 했습니다.

매일 비슷한 공부를 반복하는 것 같네요.

1. 코드 카타

[ 09:00 ~ 10:00 ]

오늘의 코드 카타는 할인 행사 였습니다.

이번에도 약간 국어 문제 느낌이 납니다.

XYZ 마트는 일정한 금액을 지불하면 10일 동안 회원 자격을 부여합니다. XYZ 마트에서는 회원을 대상으로 매일 한 가지 제품을 할인하는 행사를 합니다. 할인하는 제품은 하루에 하나씩만 구매할 수 있습니다. 알뜰한 정현이는 자신이 원하는 제품과 수량이 할인하는 날짜와 10일 연속으로 일치할 경우에 맞춰서 회원가입을 하려 합니다.
예를 들어, 정현이가 원하는 제품이 바나나 3개, 사과 2개, 쌀 2개, 돼지고기 2개, 냄비 1개이며, XYZ 마트에서 14일간 회원을 대상으로 할인하는 제품이 날짜 순서대로 치킨, 사과, 사과, 바나나, 쌀, 사과, 돼지고기, 바나나, 돼지고기, 쌀, 냄비, 바나나, 사과, 바나나인 경우에 대해 알아봅시다. 첫째 날부터 열흘 간에는 냄비가 할인하지 않기 때문에 첫째 날에는 회원가입을 하지 않습니다. 둘째 날부터 열흘 간에는 바나나를 원하는 만큼 할인구매할 수 없기 때문에 둘째 날에도 회원가입을 하지 않습니다. 셋째 날, 넷째 날, 다섯째 날부터 각각 열흘은 원하는 제품과 수량이 일치하기 때문에 셋 중 하루에 회원가입을 하려 합니다.
정현이가 원하는 제품을 나타내는 문자열 배열 want와 정현이가 원하는 제품의 수량을 나타내는 정수 배열 number, XYZ 마트에서 할인하는 제품을 나타내는 문자열 배열 discount가 주어졌을 때, 회원등록시 정현이가 원하는 제품을 모두 할인 받을 수 있는 회원등록 날짜의 총 일수를 return 하는 solution 함수를 완성하시오. 가능한 날이 없으면 0을 return 합니다.

알고리즘 짜는 데는 별 문제가 없었습니다.

class Solution {
    fun solution(want: Array<String>, number: IntArray, discount: Array<String>): Int {
        var answer: Int = 0
        var countNum = number.copyOf()
        var idx = 0
        for(i in 0..discount.size - 10) {
            countNum = number.copyOf()
            for(j in 0..9) {
                idx = want.indexOf(discount[i+j])
                if(idx != -1) countNum[idx] -= 1
            }
            if(countNum.all{ it == 0 }) answer++
        }
        return answer
    }
}

오늘은 문장만 길고, 난이도는 쉬운 편인 것 같습니다.

2. 개인 과제

[ 11:00 ~ 13:00, 15:00 ~ 17:00 ]

개인 과제 Lv. 3은 HomeActivity를 꾸미는 부분이었습니다.

특별히 더 넣을 것보다도, 값을 전달하고, 값을 받아서 텍스트 뷰로 띄우는 내용이었습니다.

그리고, 선택 구현도 동시에 진행했는데요.

이 부분에서 약간의 문제가 생겼습니다. 이 문제를 살펴보기 전에 먼저 화면부터 보여드리겠습니다.

위처럼 사진과 프로필이 뜨도록 꾸몄습니다.

사진은 컨셉에 맞게 교촌 메뉴로 만들었습니다.

2-1. registerForActivityResult

이번 과제의 선택 구현에서 가장 어렵던 부분이었습니다.

선택 구현은 회원가입을 진행한 후, 회원가입의 아이디와 비밀번호를 그대로 로그인 창으로 가져오는 내용이었습니다.

그리고, 이 부분을 구현하는 데에 registerForActivityResult를 추천하셨습니다.

제가 옛날에 이런 걸 만들 때는 startActivityForResult() 함수를 주로 사용했었는데,

이 부분이 deprecated되었다고 합니다. 그래서 registerForActivityResult를 찾아서 사용했습니다.

근데, 이 코드를 짜는 데 있어 이해가 안 되는 부분이 많았습니다.

일단, 인자로 받는 매개변수 타입인 ActivityResultContract와 ActivityResultCallback은 대체 무엇인가?

이 물음에 대한 대답을 찾기 위해, 공식 문서를 뒤져보고, 코드가 어떻게 생겼는지 확인했습니다.

먼저, ActivityResultContract는 어떤 식으로 registerForActivityResult를 진행할 것인지 정하는 것이었습니다.

registerForActivityResult는 ActivityResultLauncher를 반환하고, 이를 이용해 Contract의 기능을 수행합니다.

그래서 Contract 자리에는 ActivityResultContracts.StartActivityForResult()라는 클래스가 들어갑니다.

StartActivityForResult 는 ActivityResultContracts에 내포된 클래스입니다.

그래서 해당 내용도 다시 복습했습니다...

어쨌든, 그러면 ActivityResultCallback은 대체 어떤 놈일까요?

ActivityResultCallback은 반환받은 result를 이용할 수 있게 해주는 함수형 인터페이스입니다.

저번에 말씀드렸듯이, 인터페이스 중 함수가 하나인 경우에는 SAM 변환을 진행할 수 있습니다.

이 인터페이스도 마찬가지로, fun onActivityResult(result: O)라는 함수 하나만 갖고 있습니다.

그렇기에, 이 부분에는 람다식이 들어올 수 있게 되고, 따라서 다음과 같이 쓰게 됩니다.

 val startForRes =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == RESULT_OK) {
                    id.setText(result.data?.getStringExtra("id"))
                    pwd.setText(result.data?.getStringExtra("pwd"))
                }
            }

SignUpActivity에서 result 값을 남겨주면 이를 받아서 result 안에 담긴 resultCode와 data를 가져옵니다.

아쉽게도, 여기서 끝이 아닙니다. startForRes는 ActivityResultLauncher 타입입니다.

즉, 이를 실행시키기 위해 launch 함수를 써줘야 합니다.

startForRes.launch(intent)

그러면 이걸로 기억나서 공부하게 된 내포 클래스와 객체에 대해 얘기해보겠습니다.

3. 코틀린 공부

[ 17:00 ~ 18:00 ]

오늘은 코틀린의 내포된 클래스에 대해 얘기해보겠습니다.

코틀린에서는 내포 클래스를 쓸 수 있습니다.

class A{
	class B{
    	
    }
}

위처럼 내포 클래스를 만들 수 있습니다.

이 경우, 밖에서 저 B 클래스를 부르려면 다음과 같이 쓰면 됩니다.

A.B()

이외에도 함수나 인터페이스 안에서도 내포 클래스를 만들 수 있습니다.

다음은 Object입니다.

Object는 클래스와 달리 인스턴스 그 자체라고 봐도 됩니다.

한번 만들어두면 계속해서 쓸 수 있습니다.

Object obj {

}

이 Object는 따로 인스턴스를 생성할 수 없고, 오직 저 obj 하나만 쓸 수 있습니다.

4. 끝

이외에도 컴포지션 로컬이라는 내용을 공부했지만, 아직 더 공부해야 할 부분이 남아서 다음에 작성해보겠습니다.

그리고 오브젝트를 공부하면서 싱글톤 패턴이라는 게 나왔는데, 갑자기 정보처리기사가 생각나서 써봅니다.

정보처리기사 합격했습니다.

수첩 배송오면 더 자랑해보겠습니다.

끝.

profile
여기는 공부 기록용 블로그

0개의 댓글