안드로이드/JetPack Compose

[android/안드로이드] JetPack Compose 상태 관리

최효식 2023. 2. 22. 00:25

#공식문서

 

 

  • 컴포즈는 위의 공식문서 설명에서와 같이 이벤트가 발생해서 상태가 변경 되면 다시 변경된 상태가 내려가서 뷰가 바뀌는 단방향 데이터의 흐름을 보여줍니다.

 

 

  • 예제 코드
package com.hyosik.android.memojetpackcompose

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.hyosik.android.memojetpackcompose.ui.theme.MemoJetpackComposeTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MemoJetpackComposeTheme {

                /** 메세지 아이디 카운트 상태 */
                val clickCount : MutableState<Int> = remember {
                    mutableStateOf(0)
                }

                /** 전체 메세지 리스트 상태 */
                val messageList : SnapshotStateList<Message> = remember { mutableStateListOf() }

                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                   Column() {
                       
                       /** 1-1 onClicked 이벤트 발생  */
                       AddMessage(onClicked = {
                           clickCount.value += 1
                           val newMsg = Message(id = clickCount.value, content = "메세지 입니다 ${clickCount.value}")
                           /** 1-2 messageList 상태 변경 발생 */
                           messageList.add(newMsg)
                       })

                       /** 1-3 messageList 상태를 내려줍니다. */
                       /** 2-1 onDeleteClicked 이벤트 발생 */
                       /** 2-3 messageList 상태를 내려줍니다. */
                       MessageList(messages = messageList, onDeleteClicked = {
                         /** 2-2 messageList 상태 변경 발생 */  
                          messageList.remove(it)
                       })
                   }
                }
            }
        }
    }
}

@Composable
fun AddMessage(onClicked:() -> Unit) {
    Button(onClick = onClicked) {
        Text(text = "메세지 추가")
    }
}

@Composable
fun MessageRow(msg: Message, onDeleteClicked:(Message) -> Unit) {
    Surface(
        modifier = Modifier.padding(16.dp).fillMaxWidth(),
        shape = RoundedCornerShape(8.dp),
        border = BorderStroke(1.dp, color = Color.LightGray),
        elevation = 10.dp
    ) {
        Column(
            Modifier.padding(16.dp)
        ) {
            Text(text = "id : ${msg.id} / msg: ${msg.content}")
            Button(onClick = { onDeleteClicked(msg) }) {
                Text(text = "삭제")
            }
        }
    }
}

@Composable
fun MessageList(messages: List<Message> , onDeleteClicked:(Message) -> Unit) {
    LazyColumn {
        items(messages) { message ->
            MessageRow(msg = message , onDeleteClicked = onDeleteClicked)
        }
    }
}

@Preview(showBackground = false)
@Composable
fun DefaultPreview() {
    MemoJetpackComposeTheme {

    }
}

 

  • 1-1 onClicked 이벤트 발생
  • 1-2 messageList 에 새로운 메세지를 추가하며 리스트 상태를 변경
  • 1-3 messageList 상태가 변경됬으므로 변경된 상태를 다시 내려줘서 뷰를 랜더링 합니다.

 

추가된 메세지

 

 

  • 2-1 MessageRow 뷰에서 '삭제' 버튼으로 onDeleteClicked 이벤트를 발생
  • 2-2 messageList 에 해당 메세지를 삭제하며 리스트 상태를 변경
  • 2-3 messageList 상태가 변경됬으므로 변경된 상태를 다시 내려줘서 뷰를 랜더링 합니다.

 

메세지2 의 삭제 버튼 클릭