[TIL]Android Jetpack Compose

mandoofu·2024년 10월 26일

안드로이드

목록 보기
18/20
post-thumbnail

Compose

  • Compose는 Lambda Function(100%), DSL, Extend Function, State(UI Data Values), Stateful(Observer Pattern) 기반에 만들어졌으며 다양한 화면에 대응할 수 있는 UI/UX Framework이다.

  • DSL(Domain Specific Language : 도메인 특화 언어)

    • S/W 개발에서 특정 도메인(금융,교통,의학,공급망,UI/UX, DB Handling 등) 개발에 특화된 프로그래밍 언어 모델
  • ComposeEx

class MainActivity : ComponentActivity() {
	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContent {
			HelloComposePJTheme {
				Surface(
					modifier = Modifier.fillMaxSize(),
					color = MaterialTheme.colorScheme.background
				) {
					Greeting("Android")
					}
				}
			}
		}
	}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
	Text(
	text = "Hello $name!",
	modifier = modifier
	)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
	HelloComposePJTheme {
	Greeting("Android")
	}
}
  • Composable 함수 특징

    • @ComposableAnnotation 반드시선언
    • Composable 함수호출은 Composable 함수에서만 가능
    • Composable RecomPosition에서 Compose 함수끼리의 상태 변화를 확인하기 위해선 remember를 적용해 줘야한다
  • Modifier : Compose Modifier 속성은 모든 컴포저블 함수들의 공통적인 행위/속성을 확장 함수로 정의해 놓은 것

    • 속성 : padding, border, background, size, event handler 등
    • Compose 는 명시적으로 Margin 속성 X
      • Spacer(modifier= Modifier.width(32.dp))
      • Spacer(modifier = Modifier.height(32.dp))
      • Spacer(modifier = Modifier.width(32.dp).height(32.dp)) : chain 화
      • Margin 을 설정할 때는Size 관련 함수와 Padding 함수를 활용

Alignment(정렬) & Arrangement(배치)

  • Column = linearLayout vertical, Row = horizontal, Box = Flame

  • Alignment

    • Compose Container(Layout)에서 컴포저블들의 Vertical(Y Axis) 방향을 정렬
    • Modifier의 align(,,), alignBy(,), alignByBaseline(), spaceBy()을 이용하여개별 재조정 가능( RowScope, ColumnScope)
    • Column(자식을 세로(열) 배치) Container 시)
      • horizontalAlignment= Alignment.Start (LTL 기준 왼쪽)
      • horizontalAlignment= Alignment.CenterHorizontally(현재 Column 의 중앙)
      • horizontalAlignment=Alignment.End(LTR 기준 오른쪽)
    • Row(자식을 가로(행으로 배치))
      • verticalAlignment= Alignment.Top
      • verticalAlignment= Alignment.CenterVertically
      • verticalAlignment= Alignment.Bottom
  • Arrangement

    • Column 기준
      • verticalArrangement= Arrangement.Top
      • verticalArrangement= Arrangement.Center
      • verticalArrangement= Arrangement.Bottom
      • verticalArrangement= Arrangement.SpaceBetween
      • verticalArrangement= Arrangement.SpaceAround
      • verticalArrangement= Arrangement.SpaceEvenly
    • Row 기준
      • horizontalArrangement= Arrangement.Start
      • horizontalArrangement= Arrangement.Center
      • horizontalArrangement= Arrangement.End
      • horizontalArrangement= Arrangement.SpaceBetween
      • horizontalArrangement= Arrangement.SpaceAround
      • horizontalArrangement= Arrangement.SpaceEvenly
  • Row/Column/Box Scope

    • Compose Layout에 속한 자식들은 부모의 Scope에 존재

    • ColumnScope

      • Modifier.alignByBaseline : 자식의 베이스라인을 alignBy() or alignByBaseline() Modifier 가 이미 적용된 형제들과 정렬
      • Modifier.paddingFrom() : 자식의 정렬 라인에 패딩 추가
    • BoxScope

      • Modifier.matchParentSize() : Box 안의 자식의 크기를 부모 Box 에 맞춤

Composable State Variable

  • 컴포저블 함수의 UI 갱신을 적용하기 위함(Recomposition)

  • Compose Component 의 State 관리에 따른 상태 변수 선언 방식

    • remember
    • Kotlin Collection State Variable
      • mutableStateListOf(,,), mutableStateMapOf(,,) 등
  • Compose Runtime

    • Compose 함수를 동작 시키고 관리하는 순수 코틀린 엔진
      • Composable로 만든 UI Tree Module의 상태(State)관리를담당
  • Compose 함수내의 변수는상태변수로 선언

    • 상태변수를 갖는 컴포저블 함수를 Stateful Function 이라 하고 호출 할 때마다 상태값을 Compose Runtime은 기억하고 있어야 함(Snapshot)
    • 상태변수는 Observer(관찰자) 가 존재
  • remember(keyword 함수) & MutableState

    • emember 를 이용해 상태변수를 선언
    • MutableState
      • mutableStateOf(,,,)를 이용해 상태변수 초기값을 Builder
      • MutableState 는 Observable Type
        • 상태 값에 대한 관찰자가 생성(상태 값이 변경되면 영향을 받는 모든 컴포즈 함수는 재구성 됨을 명심)
//위임 방식으로 문자열 var 가 됨
var currentTIValue1 by remember { mutableStateOf("") }
val textChangeEvent = { enteredText: String ->
currentTIValue1 = enteredText
}
  • rememberSaveable : 가로세로 모드 변경 시 이전 상태 값을 저장하는 용도

  • UDF(Unidirectional Data Flow(단방향 데이터 접근 방식))

    • 앱 개발 시 UDF 접근 방식은 부모 컴포저블의 상탯값을 자식 컴포저블
      에서 직접 변경해서는 안된다는 개념
  • State Hoisting(상태 호이스팅)

    • 부모 컴포저블에서 자식 컴포저블로 상태 값을 전달하는 방식이며 컴포저블 함수 재사용성 향상
      - 이벤트 핸들링 코드는 람다(고차함수)를 전달
  • CompositionLocal

    • 상태를 선언할 때 컴포즈 트리에서 될 수 있으면 높은 노드로 선언하
      는 것이 일반적 구현 기법(상태 호이스팅)
  • Compose Lazy List (지연 목록 (view Holder))

    • LazyRow, LazyColumn, LazyVerticalGrid, LazyHorizontalGrid
  • 화면에 보이는 부분만 아이템을 만들어 냄

  • 스크롤을 하면 현재 화면에서 벗어난 아이템들은 자동 파기

    • 아이템은 다시 보일 때 만들어짐
    • 무한한 리스트도 성능저하 없이 화면에 렌더링 가능
  • LazyListScope가 Lazy List 에는 존재

  • LazyListScope 중요 함수

    • items(, ,) : repeat value(Int), List, Array<*>
LazyColumn{
	items(List Object){ index ->
		//Item Composable UI/UX
		, , , , ,
  }
 }
  • Lazy List Scroll State (⭐)

    • Lazy List Scroll은 Default true
    • List 가 CRUD 시 스크롤의 동작 방식을 결정하는 특별한 상태 변수이
      며 Coroutine Scope 에서 동작해야 함
  • Slot API(Slot Based Layout Composable) (⭐)

    • 정적 컴포저블
      • 함수 작성(코딩)시에 미리 정의된 화면(고정된 UI 등)
    • 동적 컴포저블
      • 런타임시 끼워 넣을 수 있는 컴포저블(layout, widget 등)을 의미
    • Slot Based Layout Composable
      • 정적 컴포즈 뿐 아니라 하나 이상의 동적(런타임) 컴포저블을 포함할 수 있는 layout interface template 을 의미
      • Slot 함수의 인자에 컴포저블 람다(content: @Composable () -> Unit)를 사용
      • androidx.compose.material:material을기반으로 한 다양한 컴포저블을 제공
  • Scaffold(Slot API)

    • 복잡한 사용자 인터페이스를 위한 표준화된 플랫폼을 제공하는 기본 구조(Layout Framework의 한 종류)
    • TopBar,BottomBar,FAB및 Drawer와 같은 가장 일반적인 최상위(메인화면) Material Component 대한 Slot을 제공하는 중요한 역할을 담당
  • Jetpack Compose Navigation 구성요소

    • Navigation Graph

      • 앱에서 화면을 이루는 전체 구조를 의미
    • Navigation Destination

      • 앱을 구성하는 각 화면을 의미(컴포저블 또는 Activity)
    • Navigation Back Stack

      • 앱 안에서 destination(화면)에 이르는 사용자의 경로(Path)를 추적
      • 사용자가 다른 destination으로 전환 시 전환된 화면은 current destination 이 되고 그 전 destination은 백 스택에 놓여 짐
        • 사용자가 다른 화면으로 이동할 때마다 전 화면은 스택에 쌓이고 백 키를 누르면 백 스택에 있던 화면이 현재 화면으로 전환 됨
    • Navigation Back Stack 제어

      • navigate() 함수의 후행 람다 popUpTo() 함수 사용
        • 목적지로 가기 전에 스택에 있던 화면을 꺼내고 원하는 화면을 바로 백스택에 넣을 수 있음

Compose MVVM

  • 컴포즈 상태(State) 기반 ViewModel

    • 컴포즈의 UI State 변환 관찰이 주 목적
      • Clean Architecture(안드로이드 MVVM)의 목적은 Task 에서 각 역할의 관심사를 분리하는 것이 목적이므로 컴포즈 MVVM은 Repository or Data Source(Room , REST 등), Usecase등은 변함이 없다
    • 컴포즈(Presentation == UI State) 와 ViewModel 관계만 이해하면 됨
  • 컴포즈에서 Flow 값 수집(소비)

    • collectAsState

      • 현재 화면이 백그라운드에 있어도 flow 작업이 활성화된 상태로 유지
        • 리소스 낭비 발생
      • flow를 수집하는데 플랫폼에 종속되는 않는 API
    • collectAsStateWithLifecycle

      • 컴포즈 함수 Lifecycle을 인식하여 최신 값의 Compose State 갱신
        • 컴포즈가 백그라운드에 존재 시 값을 수집하지 않으므로 리소스 낭비를 최소화 할 수 있음
        • flow 최신 값을 Compose State 변수에 업데이트
        • Default 로 Lifecycle.State.STARTED 로 시작

Compose Effect

  • SideEffect란 함수가 만들어진 목적과 다른 효과가 함수내에서 발생
  • UI 작업과분리된Coroutine Scope 로보통작업을진행
  • Jetpack Compose Side-Effect 컴포저블함수들
    • SideEffect
      • 재구성이 성공할 때마다 Effect가 실행
        • 재구성이 완료 될 때마다 블럭 내의 작업이 실행
        • 주기적으로 재구성 될 때 호출되는 Side-Effect 시 사용
      • Coroutine(비동기) 작업은 블럭에서 실행하지 않고, 주로 상태 업데이트에 사용
    • LaunchedEffect
      • 재구성이 시작하면 매개변수로 전달된 코드 블록으로 코루틴이 실행
      • 컴포지션을 종료하면 코루틴이 취소
      • 키 값을 이용해 키 값이 바뀌면 코드 블럭을 실행되게 할 수 있음
    • DisposableEffect
      • Dispose될 때 정리되어야 할 Side Effect를 정의
      • key값은 DisposableEffect가 재 수행되는 것을 결정하는 파라미터
    • produceState
      - remember + LaunchedEffect 를 결합한 함수
      - 초기값이 변할 때마다 코루틴 실행하며 변경된 값을 가져올 때
    • derivedStateOf
      • 기존 상태에서 다른 상태를 원할 때
      • derivedStateOf 의 변경에 따라 UI 상태의 변경을 원할 때

0개의 댓글