ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Jetpack Compose] 스낵바 표시, MutableState 사용기법에 대해
    안드로이드 2023. 3. 18. 22:39

    Jetpack Compose 에서 스낵바를 표시하고 MutableState 사용하는 몇 가지 방법에 대해 알아보자.

     

    먼저 스낵바는 Scaffold 컴포넌트를 이용해 사용할 수 있다.

     

    컴포즈에서는 Material component composable 들을 기본으로 제공하는데, Scaffold 컴포넌트를 최상위에 두면 하위 컴포넌트들에서 Material 컴포넌트들을 이용할 수 있다.

     

    그래서 스낵바를 어떻게 띄우냐,

    val scaffoldState = rememberScaffoldState()
    val scope = rememberCoroutineScope()
    
    Button(onClick = {
    	scope.launch {
    		scaffoldState.snackbarHostState.showSnackbar("hello World!")
    	}
    })

    Scaffold 를 이용하기 위해 필요한 Scaffold State 를 rememberScaffoldState 를 이용해 받고,

    스낵바를 호출하는 showSnackbar 메소드는 suspend 메소드로 CoroutineScope 내부에서 호출해주어야 하기 때문에 rememberCoroutineScope() 를 이용해 CoroutineScope 또한 받아준다.

     

    여기서 suspend 메소드란, 메소드 내부에서 일시중지가 가능한 작업이 있는 메소드를 말하는 것인데, 사용자 UI 에 문제가 생길 수 있어 메인 쓰레드에서 호출할 수 없고 CoroutineScope 를 이용해 별도 쓰레드에서 호출하는 것이다.

     

    이후, 버튼을 생성하고 버튼을 클릭했을 때 scope.launch 를 통해 CoroutineScope 를 동작시키고 그 내부에서 showSnackbar 메소드를 통해 스낵바를 생성시켜준다.

     

    요렇게 하단에 스낵바가 표시됩니다

     

    이번엔 MutableState 를 사용하는 기법들에 대해 알아보자.

     

    먼저 구조분해 기법이다.

     

    보통 MutableState 는 컴포즈에서 remember 구문과 함께 사용된다.

    컴포즈는 화면 회전 등을 통해 State 값이 변경되면 화면을 재구성하면서 기존의 값들이 모두 초기화된다. 만약, 화면 회전에도 기억되어야 하는 값이 있다면 remember 구문을 통해 아래와 같이 값을 저장할 수 있다.

    val temp = remember() {
    	mutableStateOf("")
    }

    위와 같이 선언하게 되면, temp 변수는 아래와 같이 MutableState 형이 된다.

    이렇게 선언되면 사용할때 좀 귀찮더라구요

    컴포즈에서는 TextField 를 이용하기 위해선 변경되는 값으로 직접 value 를 설정해주는 작업이 필요하므로, temp 변수의 값을 TextField 에 사용하려면 아래와 같이 .value 프로퍼티를 이용해야 한다.

    TextField(value = temp.value, onValueChange = {
    	temp.value = it
    })

    String 형이 아닌 MutableState 형으로 만들어지다 보니 값을 바로 사용할 수 없게 된 것이다.

     

    이런 귀찮음을 방지하기 위해 MutableState 인터페이스의 내부 구조를 확인해보면, 아래와 같이 component1() 메소드와 component2() 메소드 2개가 operator 를 이용해 선언되어 있는 것을 볼 수 있다.

    오..

    여기서 잠깐 코틀린에서의 구조분해에 대해 알아보자면, operator 라는 연산자 오버로딩을 이용한 것이다.

    operator fun componentN() 과 같이 선언하게 되면 1 부터 N 까지 해당 순서에 맞는 함수가 각각의 변수에 할당되게 된다.

     

    위 코드에서 component1 은 MutableState 의 실제 value 를 반환해주는 getter 역할을 하고, component2 는 value 값을 넣어주는 setter 역할을 하는 것을 볼 수 있다.

     

    따라서 이를 이용해 아래와 같이 구조분해 형식으로 MutableState 를 이용할 수 있다.

    val (text, setValue) = remember() {
    	mutableStateOf("")
    }

    text 에는 component1 이 할당되고, setValue 에는 component2 가 할당되어 결과적으로는 text 에 실제 value 값이 할당되고, setValue 는 value 를 세팅해주는 함수가 할당되게 된다.

     

    이를 이용해 TextField 를 생성하면,

    TextField(value = text, onValueChange = setValue)

    깔끔하게 TextField 를 이용할 수 있다.

     

    두 번째 MutableState 를 이용하는 방법은, by 키워드를 사용하는 것이다.

     

    by 키워드를 이용해서 MutableState 의 getValue 와 setValue 동작에 대한 Delegation (해당 동작을 객체에 위임시킴) 이 일어나고, 이 객체에서 getValue 와 setValue 모두가 동작해야 하기 때문에 아래와 같이 val 이 아닌 var 로 생성되어야 한다.

    var temp by remember {
    	mutableStateOf("")
    }

    이것도 TextField 에 이용하면 방법을 확인해보면,

    TextField(value = temp, onValueChange = {
    	temp = it
    })

    .value 프로퍼티를 이용하지 않아도 실제 값에 접근이 가능한 것을 볼 수 있다.

     

    이 by 키워드를 완벽하게 이해하기 위해선 Delegate 패턴에 대한 이해가 필요한데, 이 내용은 다음 포스팅에서 추가적으로 다뤄봐야 할 것 같다.

    '안드로이드' 카테고리의 다른 글

    Object 와 Companion Object 의 차이점에 대해  (0) 2023.04.09
    sealed class 란?  (0) 2023.04.02
    Firebase Crashlytics 에 대해  (0) 2023.03.05
    [Jetpack Compose] 위젯에 대해  (0) 2023.01.06
    [Jetpack Compose] 너는 뭐냐  (0) 2023.01.06

    댓글

Designed by Tistory.