Compose 기억할 만한 정보

손현수·2024년 9월 3일

프로젝트를 진행하며 Compose로 개발할 때 주의할 점에 대해 정리해보자

Dialog와 같은 객체를 선언할 때는 remember로 감쌀 수 있는지 고려해보자

    val datePickerDialog = DatePickerDialog(
        context,
        R.style.DatePickerStyle,
        { _, year, month, day ->
            if(isClickedStartDay) startDay = TimeFormatter.getDatePickerDashDate(year, month, day)
            else endDay = TimeFormatter.getDatePickerDashDate(year, month, day)
        },
        calendar.get(Calendar.YEAR),
        calendar.get(Calendar.MONTH),
        calendar.get(Calendar.DAY_OF_MONTH)
    )
	val datePickerDialog = remember {
        DatePickerDialog(
            context,
            R.style.DatePickerStyle,
            { _, year, month, day ->
                if(isClickedStartDay) startDay = TimeFormatter.getDatePickerDashDate(year, month, day)
                else endDay = TimeFormatter.getDatePickerDashDate(year, month, day)
            },
            calendar.get(Calendar.YEAR),
            calendar.get(Calendar.MONTH),
            calendar.get(Calendar.DAY_OF_MONTH)
        )
    }
  • 두 방식을 비교했을 때 첫번째 방식은 재구성될 때마다 새로 객체가 생성될 수 있으므로 remember를 사용하면 재구성에 따른 무분별한 객체 생성을 방지할 수 있다.

LaunchedEffect를 사용할 때는 중복 데이터 처리에 주의하자

LaunchedEffect(scrollState) {
	snapFlow { scrollState.firstVisibleItemIndex }
    	.collect { index ->
        	isFilterAtTop = index >= 2
        }
}
LaunchedEffect(scrollState) {
	snapFlow { scrollState.firstVisibleItemIndex }
    	.distinctUntilChanged()
    	.collect { index ->
        	isFilterAtTop = index >= 2
        }
}
  • distinctUntilChanged()를 사용하면 scrollState의 값에는 변화가 존재하지만 scrollState.firstVisibleItemIndex의 값이 변하지 않았을 때, 중복 데이터 처리를 방지할 수 있다.
  • 예를 들어 사용자가 미세하게 스크롤을 수행하여 화면 상에 보여지는 첫번째 아이템에 변화가 없을 때에 유용하다.

remember를 파라미터에 사용하지 말자

Image(
	modifier = Modifier
    	.clickable(
        	interactionSource = remember { MutableInteractionSource() }
            // 생략
        )
)
val interactionSource = remember { MutableInteractionSource() }

Image(
	modifier = Modifier
    	.clickable(
        	interactionSource = interactionSource
            // 생략
        )
)
  • 첫번째 방법의 경우 Image 컴포저블이 재구성될 때마다 interactionSource가 재구성되기 때문에 리소스가 낭비될 수 있다.
  • 따로 변수를 선언하여 사용하면 재사용성이 증가하고 재구성에 따른 리소스 낭비를 줄일 수 있다.

Util 객체는 Hilt의 도움을 받아 의존성을 주입받는 것이 단위 테스트에 용이하다

@HiltViewModel
class DogmaniaViewModel @Inject constructor(
	
): BaseViewModel<DogmaniaPageState>(DogmaniaPageState()) {
	private val today = TimeFormatter.getToday()
    private val year = TimeFormatter.getYear(today)
    private val month = TimeFormatter.getMonth(today)
    
    // 생략...
}
@HiltViewModel
class DogmaniaViewModel @Inject constructor(
	private val timeFormatter: TimeFormatter
): BaseViewModel<DogmaniaPageState>(DogmaniaPageState()) {
	private val today = timeFormatter.getToday()
    private val year = timeFormatter.getYear(today)
    private val month = timeFormatter.getMonth(today)
    
    // 생략...
}
  • 크게 차이는 없지만 단위 테스트 관점에서 본다면 유용하다고 한다.
profile
안녕하세요.

0개의 댓글