Slot API
이름을 보면 알 수 있는 것 처럼 뭔갈 넣을 수 있도록 만드는 것이다. 즉 재사용성이 좋도록 함수를 설계하는 것이다.
말만 들어서는 기존의 재사용성 높은 함수와 다를바가 없어 보일 것이다. 자세하게 정리하며 설명 들어가보자.
목적
일단 이걸 왜 써야할까? 앞서 말했던것 처럼 재사용성이다. 극한의 재사용성이 목표다. 하나의 큰 틀을 만들고, 그 틀을 세부적으로 활용하며 사용하기 위해서 Slot API를 사용한다. 아래 사용법을 보면서 공부해보자.
사용법
기존의 코드를 먼저 보자.
@Composable
fun ButtonFun(){
var count = remember {
mutableStateOf(0)
}
Row(
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = { count.value++ }) {
Text(text = count.value.toString())
}
Text(text = "Click!")
}
}
클릭할때마다 글자가 바뀌는 버튼을 만들면 대략 위와 같은 느낌이 가장 먼저 생각날거다.
여기서 count를 외부에서 받아와서 적용하는 방법을 쓴다면, 한층 재사용성이 높아진다.
@Composable
fun ButtonFun(
count: MutableState<Int>
){
Row(
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = { count.value++ }) {
Text(text = count.value.toString())
}
Text(text = "Click!")
}
}
count는 외부에서 선언하고, 함수 내부에서 사용할 수 있다. 즉, 함수와 count 변수와의 의존성을 없애는 것이다.
여기서 count가 클릭되었을때 실행되는 함수 또한 외부에서 받아올 수 있다.
@Composable
fun ButtonFun(
count: Int,
onClick: () -> Unit
){
Row(
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = { onClick() }) {
Text(text = count.toString())
}
Text(text = "Click!")
}
}
외부에 존재하는 count를 가져오고, 그 값을 변경시키는 코드(버튼이 클릭되었을때 사용되는 코드)를 외부에서 가져와서 함수와의 의존성 또한 없앨 수 있다. 이때 count가 Mutable값이 단순 Int로 변화하는 이유는 무엇일까? 정답은 의존성의 변화이다. onClick함수가 외부에서 선언되기 때문에 count의 값 또한 외부에서 변화를 줘야 한다.
여기서 내부에 존재하는 Text또한 외부에서 가져올 수 있다.
@Composable
fun ButtonFun(
count: Int,
onClick: () -> Unit,
content: @Composable () -> Unit
){
Row(
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = { onClick() }) {
Text(text = count.toString())
}
content()
}
}
content: @Composable () -> Unit 이게 핵심이다.
외부에서 Composable 함수를 가져와서 내부에 사용할 수 있다. 겉으로 보기엔 Text를 내부에 적는것과 다를게 없어 보인다. 하지만, 결정적인 차이점이 존재한다. 바로 재사용성이다.
이게 뭔소린가 싶을 수도있다. 매개변수로 Text를 받으면 재사용성이 좋지 않나?? 싶을 수 있다.
매개변수가 Text라면 Text만 받을 수 있지만, Composable로 한다면 Text뿐만 아니라 Button, Image 등 다양한 Composabel 함수들을 매개변수로 사용할 수 있다.
여기서 한단계 더 발전시켜보자.
@Composable
fun ButtonFun(
count: Int,
onClick: () -> Unit,
content: @Composable RowScope.() -> Unit
){
Row(
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = { onClick() }) {
Text(text = count.toString())
}
content()
}
}
RowScope라는걸 추가해줬다. 왜일까?
내부에 Row가 존재하고있다. 그리고, content가 Row내부에 사용되고 있기 때문에 RowScope가 적용될 수 있도록 사용해준 것이다.
결론
꽤나 유용하다. 버튼들을 만들때도 사용할 수 있을것 같다. 이것 외에도 같은 틀을 가진 함수를 여러개 만들어야 할때 주로 사용할 수 있을 것 같다.