코딩하는 일용직 노동자

MVI 라이브러리 Orbit 본문

안드로이드

MVI 라이브러리 Orbit

bacass 2025. 12. 31. 11:15

https://github.com/orbit-mvi/orbit-mvi

 

GitHub - orbit-mvi/orbit-mvi: A simple MVI framework for Kotlin Multiplatform and Android

A simple MVI framework for Kotlin Multiplatform and Android - orbit-mvi/orbit-mvi

github.com

MVI 패턴을 쉽고 안전하게 구현할 수 있도록 도와주는 라이브러리이다.

data class CalculatorState(
    val total: Int = 0
)

sealed class CalculatorSideEffect {
    data class Toast(val text: String) : CalculatorSideEffect()
}

 

class CalculatorViewModel: ContainerHost<CalculatorState, CalculatorSideEffect>, ViewModel() {

    // Include `orbit-viewmodel` for the factory function
    override val container = container<CalculatorState, CalculatorSideEffect>(CalculatorState())

    fun add(number: Int) = intent {
        postSideEffect(CalculatorSideEffect.Toast("Adding $number to ${state.total}!"))

        reduce {
            state.copy(total = state.total + number)
        }
    }
}

 

class CalculatorActivity: AppCompatActivity() {

    // Example of injection using koin, your DI system might differ
    private val viewModel by viewModel<CalculatorViewModel>()

    override fun onCreate(savedState: Bundle?) {
        ...

        addButton.setOnClickListener { viewModel.add(1234) }

        viewModel.observe(state = ::render, sideEffect = ::handleSideEffect)
    }

    private fun render(state: CalculatorState) {
        ...
    }

    private fun handleSideEffect(sideEffect: CalculatorSideEffect) {
        when (sideEffect) {
            is CalculatorSideEffect.Toast -> toast(sideEffect.text)
        }
    }
}

 

@Composable
fun CalculatorScreen(viewModel: CalculatorViewModel) {

    val state = viewModel.collectAsState().value

    viewModel.collectSideEffect { handleSideEffect(it) }

    // render UI using data from 'state'
    ...
}

private fun handleSideEffect(sideEffect: CalculatorSideEffect) {
    when (sideEffect) {
        is CalculatorSideEffect.Toast -> toast(sideEffect.text)
    }
}