Compose 사용하는 이유 및 이해(1)

푸른하늘·2022년 6월 28일
0

컴포즈

목록 보기
1/5
post-thumbnail

🍎 Compose 사용해야 하는 이유

🍏 코드 감소

  • XML +Activity => Compose
  • RecyclerView Adpater => LazyColum()
  • 훨씬 더 단순하기 때문에 추론하기도 쉽고 복잡한 구성요소 코드도 쉽게 읽힘

🍏 직관적

  • 선언적 API를 사용해서 UI를 단지 설명하기만 하면 됩니다
  • 상태가 명시적이며 컴포저블로 전달됩니다. 앱 상태가 변경되면 UI가 자동으로 업데이트
  • 특정 활동이나 프래금너트에 종속되지 않은 작은 스테이트리스(Stateless) 구성요소를 빌드합니다.

🍏 빠른 개발 과정

  • Views를 Compose 코드에서 호출 할 수 있으며 Navigation , ViewModel 어디서든 같이 작동 할 수 이씁니다
  • 미리 보기 기능을 통해 빌드를 하지 않고 빠르고 반복적으로 수정 할 수 있습니다

🍏 강력한 성능

  • 애니메이션을 통해 쉽게 빠르게 앱에 움직임과 생명을 넣을수 있습니다.
  • 플랫폼 API에 직접 액세스하고 머티리얼 디자인, 어두운 테마, 애니메이션 등을 기본적으로 지원합니다

🍎 Compose 이해

🍏 선언형 프로그래밍 패러다임

뷰를 수동으로 조작하면 오류가 발생할 가능성이 커집니다. 그리고 데이터를 여러 위치에서 렌더링한다면 실수해서 빼먹는 가능성이 있으며 유지관리 복잡성이 증가합니다.

그래서, 선언형 UI 모델로 전환하기 시작했으며,이에 따라 ㅂ질드 및 엔지니어링이 크게 감소해씁니다. 처음부터 화면 전체를 개념적으로 재생성한 후 필요한 변경사항만 적용하는 방식입니다.


@Composable

  • 주석으로 지정되며, 모든 구성 가능한 함수에는 이 주석이 있어야합니다.
    이 함수는 데이터를 UI로 변경하기 위한 함수란느 것을 Compose 컴파일러에게 알린다.
  • 매개변수로 String인 name을 받으며 Text기능을 호출하여 값을 넣습니다
  • 함수는 아무것도 반환하지 않습니다 . Compose 함수는 UI 위젯을 구성하는 대신 원하는 화면의 상태를 선언함으로 아무것도 반환할 필요가 없습니다.

🍏 선언형 프로그래밍 전환

  • 위젯은 비교적 스테이트리스(Stateless) 상태이며 setter 또는 getter 함수를 노출하지 않습니다
  • 동일한 구성 가능한 함수를 다른 인수로 호출하여 UI를 업데이트합니다
  • 이렇게 하면 앱 아키텍처 가이드에 설명된 대로 ViewModel과 같은 아키텍처 패턴에 상태를 쉽게 제공할 수 있습니다.

앱아킥테쳐 가이드

  • 관심사 분리
  • 데이터 모델에서 UI 도출하
    • 앱을 제거해도 데이터 삭제 X
    • 네트워크 연결이 취약하거나 연결되어 있지 않아도 앱이 계속 작동한다.

그림<1> 데이터를 사용하여 다른 컴포저블을 호출하는 그림

그림<2> 사용자가 UI 요소와 상호작용하여 이에 따라 이벤트 트리거되며 앱 로직이 이벤트에 응답합니다.

🍎 재구성

Compose에서는 새 데이터를 사용하여 구성 가능한 함수를 다시 호출합니다. 이에 따라 함수가 재구성되며 , 필요한 경우 새 데이터로 다시 그려집니다.

@Composable
fun ClickCounter(clicks: Int, onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("I've been clicked $clicks times")
    }
}
  • 버튼이 클릭될 때 Clicks 값을 업데잍 ㅡ합니다.
  • Text 함수를 사용해 람다를 다시 호출하여 새 값을 표시합니다.
  • 함수의 입력이 변경될 때 발생합니다.

🍏 재구성 비용이 많을 경우

  • 백그라운드 코루틴에서 작업을 실행하고 값 결과를 매개변수로 전달합니다.
  • 다음코드와 같이 컴포저블 함수를 만들어 SharedPreferences 의 값을 업데이트 합니다.
@Composable
fun SharedPrefsToggle(
    text: String,
    value: Boolean,
    onValueChanged: (Boolean) -> Unit
) {
    Row {
        Text(text)
        Checkbox(checked = value, onCheckedChange = onValueChanged)
    }
}

코드 설명

  • SharedPresToggle 안에 매개변수로 text, value, onValueChanged를 받습니다
  • Row로 구성하여 Text, CheckBox가 겹치지 않게 구성합니다
  • Text( 매개변수값) 삽입
  • CheckBox( 매개변수 값 삽입)

🍏특징

⚡️함수는 순서와 관계없이 실행할 수 있습니다.

  • StartScreen, MiddleScreen 및 EndScreen 호출은 순서와 관계없이 발생할 수 있습니다
@Composable
fun ButtonRow() {
    MyFancyNavigation {
        StartScreen()
        MiddleScreen()
        EndScreen()
    }
}

⚡️함수는 동시에 실행할 수 있습니다.

  • 잘못된 예시 코드
    • 함수가 로컬 변수에 쓰는 경우 이 코드는 스레드로부터 안전하지 않거나 적절하지 않습니다.
@Composable
fun ListComposable(myList: List<String>) {
    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        Column {
            for (item in myList) {
                Text("Item: $item")
            }
        }
        Text("Count: ${myList.size}")
    }
}
  • 올바른 예시 코드
    • 변수를 함수 안에 저장 한다
    • items는 모든 재구성을 통해 수정됩니다.
@Composable
@Deprecated("Example with bug")
fun ListWithBug(myList: List<String>) {
    var items = 0

    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        Column {
            for (item in myList) {
                Text("Item: $item")
                items++ // Avoid! Side-effect of the column recomposing.
            }
        }
        Text("Count: $items")
    }
}

⚡️ 재구성은 최대한 많은 수의 구성 가능한 함수 및 람다를 건너뛴다.

  • UI의 일부가 잘못된 경우 Compose는 업데이트해야 하는 부분만 재구성하기 위해 최선을 다합니다.
@Composable
fun NamePicker(
    header: String,
    names: List<String>,
    onNameClicked: (String) -> Unit
) {
    Column {
        //  [names]가 변경할 때가 아닌 [header]가 변경할때 재구성 한다.
        Text(header, style = MaterialTheme.typography.h5)
        Divider() // 구분선 html<hr> 비슷함

        // LazyColumn은 RecyclerView의 Compose버전이다.
        // items()는 RecyclerView.ViewHolder의 역할과 비슷하다.
        LazyColumn {
            items(names) { name ->
                 // 아이템의 [name] 이 업데이트 될때 어댑터의 아이템이 재구성된다.
                // [header] 변경될때는 재구성하지 않는다.
                NamePickerItem(name, onNameClicked)
            }
        }
    }
}

/**
 * Display a single name the user can click.
 */
@Composable
private fun NamePickerItem(name: String, onClicked: (String) -> Unit) {
    Text(name, Modifier.clickable(onClick = { onClicked(name) }))
}

⚡️ 재구성은 낙관적이며 취소될 수 있습니다

  • 포저블의 매개변수가 변경되었을 수 있다고 생각할 때마다 재구성이 시작됩니다.
  • 매개변수가 다시 변경되기 전에 재구성을 완료할 것으로 예상합니다.
  • 재구성이 완료되기 전에 매개변수가 변경되면 Compose는 재구성을 취소하고 새 매개변수를 사용하여 재구성을 다시 시작할 수 있습니다.

⚡️ 구성 가능한 함수는 매우 자주 실행될 수 있음

  • 기기 저장소에서 읽기와 같이 비용이 많이 드는 작업을 실행하면 이 함수로 인해 UI 버벅거림이 발생할 수 있습니다.
profile
Developer-Android-CK

0개의 댓글