Airbnb Mavericks에서는 Compose와 Dagger/Hilt를 모두 지원한다.
이를 사용하기 위해서는 기존 mavericks와 더불어 mavericks-compose, mavericks-hilt를 추가해주어야 한다.
// build.gradle
// mavericks
implementation("com.airbnb.android:mavericks:3.0.9")
implementation("com.airbnb.android:mavericks-compose:3.0.9")
implementation("com.airbnb.android:mavericks-hilt:3.0.9")
// compose
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3-android")
// di
implementation("com.google.dagger:hilt-android:2.51.1")
implementation("com.google.dagger:hilt-android-compiler:2.51.1")
implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
Compose와 Hilt를 사용한 프로젝트에 Mavericks를 도입한다고 해서 기존 코드에 큰 변화를 줄 필요는 없다.
먼저 기존 State에 MavericksState를 implement 하면 MavericksState가 된다.
data class AppState(
val property1: Int = 0,
val property2: Int = 0
): MavericksState
다음으로 AppViewModel의 @Inject를 @AssistedInject로 변경한 후 constructor에서 @Assisted Annotation을 추가하고 사용할 State를 명시하면 된다.
이후
AssistedViewModelFactory<ViewModel, State>,
MavericksViewModelFactory<ViewModel, State> 두 코드를 추가해주면 된다.
State를 변경할 때는
setState { copy(property = newValue) } 를 사용하면 State를 업데이트 한다.
만약 initialState를 companion object의 initialState를 override해서 초기값의 리턴을 바꿔줄 수 있다.
아래와 같은 형식으로 ViewModel을 선언한다.
class AppViewModel @AssistedInject constructor(
@Assisted initialState: AppState
) : MavericksViewModel<AppState>(initialState) {
@AssistedFactory
interface Factory : AssistedViewModelFactory<AppViewModel, AppState> {
override fun create(state: AppState): AppViewModel
}
companion object :
MavericksViewModelFactory<AppViewModel, AppState> by hiltMavericksViewModelFactory()
}
이 후 AppViewModelModule을 생성하여 viewModel에서 선언한 viewModelFactory의 의존성 주입 코드를 작성해주어야 한다.
아래와 같은 형식으로 작성을 하면 ViewModel과 관련된 변경은 끝이다.
@Module
@InstallIn(MavericksViewModelComponent::class)
interface AppViewModelModule {
@Binds
@IntoMap
@ViewModelKey(AppViewModel::class)
fun appViewModelFactory(factory: AppViewModel.Factory): AssistedViewModelFactory<*, *>
}
@Composable
fun AppView() {
val viewModel: AppViewModel = mavericksViewModel()
val property2 by viewModel.collectAsState(AppState::property2)
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Property1View()
Spacer(modifier = Modifier.size(16.dp))
Property2View(
property2 = property2,
decreaseProperty2 = { viewModel.sendIntent(AppIntent.DecreaseProperty2) },
increaseProperty2 = { viewModel.sendIntent(AppIntent.IncreaseProperty2) })
}
}
Compose에서 기존에는 viewModel을 사용할 때
val viewModel: AppViewModel = hiltViewModel()을 사용했다면
val viewModel: AppViewModel = mavericksViewModel()로 바꿔주면 viewModel을 사용할 수 있다.
위에서 viewModel에 주입한 State를 View에서 사용할 때는
val property by viewModel.collectAsState(AppState::property) 와 같이 사용하면 property의 변화를 감지해서 UI에서 즉각적으로 렌더링을 수행할 수 있다.