<!DOCTYPE html> <html lang="en-us"> <head><script src="/livereload.js?mindelay=10&v=2&port=49905&path=livereload" data-no-instant defer></script> <title> MVI Architecture Helper | codeskraps </title> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="Your website description"> <meta name="generator" content="Hugo 0.134.3"> <link rel="canonical" href="http://localhost:49905/posts/mvi_architecture/" > <link href="/css/style.min.38d8ec3c7cca8185fe94ab7dc7ca79d69e14b78ca3c077807b2c32725df95c62.css" rel="stylesheet"> </head> <body> <div class="flexWrapper"> <header class="headerWrapper"> <div class="header"> <div> <a class="terminal" href="http://localhost:49905/"> <span>me@codeskraps.com ~ $</span> </a> </div> <input class="side-menu" type="checkbox" id="side-menu"> <label class="hamb" for="side-menu"><span class="hamb-line"></span></label> <nav class="headerLinks"> <ul> <li> <a href="http://localhost:49905/projects/" title="" > ~/projects</a> </li> <li> <a href="http://localhost:49905/about/" title="" > ~/about</a> </li> <li> <a href="http://localhost:49905/posts/" title="" > ~/posts</a> </li> </ul> </nav> </div> </header> <div class="content"> <main class="main"> <div class="postWrapper"> <h1>MVI Architecture Helper</h1> <section class="postMetadata"> <dl> <dt>tags</dt> <dd><span></span> <a href="/tags/kotlin/">#Kotlin</a><span></span> <a href="/tags/kmp/">#Kmp</a><span></span> <a href="/tags/android/">#Android</a><span></span> <a href="/tags/mvi/">#Mvi</a></dd> <dt>published</dt> <dd><time datetime="2024-09-27">September 27, 2024</time></dd> <dt>reading time</dt> <dd>1 minute</dd> </dl> </section> <div> <p>Something smart to talk about this helper class</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-kotlin" data-lang="kotlin"><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">StateReceiver</span><STATE> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">suspend</span> <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">updateState</span>(transform: <span style="color:#66d9ef">suspend</span> (STATE) <span style="color:#f92672">-></span> STATE) </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">suspend</span> <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">withState</span>(block: <span style="color:#66d9ef">suspend</span> (STATE) <span style="color:#f92672">-></span> Unit) </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">suspend</span> <span style="color:#66d9ef">inline</span> <span style="color:#66d9ef">fun</span> <<span style="color:#66d9ef">reified</span> <span style="color:#a6e22e">TYPE</span> : <span style="color:#a6e22e">STATE</span>, <span style="color:#a6e22e">STATE</span>> <span style="color:#a6e22e">StateReceiver</span><STATE>.withType(<span style="color:#66d9ef">crossinline</span> block: <span style="color:#66d9ef">suspend</span> (TYPE) <span style="color:#f92672">-></span> Unit) { </span></span><span style="display:flex;"><span> withState { state <span style="color:#f92672">-></span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (state <span style="color:#66d9ef">is</span> TYPE) { </span></span><span style="display:flex;"><span> block(state) </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">suspend</span> <span style="color:#66d9ef">inline</span> <span style="color:#66d9ef">fun</span> <<span style="color:#66d9ef">reified</span> <span style="color:#a6e22e">TYPE</span> : <span style="color:#a6e22e">STATE</span>, <span style="color:#a6e22e">STATE</span>> <span style="color:#a6e22e">StateReceiver</span><STATE>.updateWithType(<span style="color:#66d9ef">crossinline</span> transform: <span style="color:#66d9ef">suspend</span> (TYPE) <span style="color:#f92672">-></span> TYPE) { </span></span><span style="display:flex;"><span> withType<TYPE, STATE> { state <span style="color:#f92672">-></span> updateState { transform(state) } } </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">StateProvider</span><STATE> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">val</span> state: StateFlow<STATE> </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IntentReceiver</span><INTENT> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">handleIntent</span>(intent: INTENT) </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ActionProvider</span><ACTION> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">val</span> action: Flow<ACTION> </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ActionReceiver</span><ACTION> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">suspend</span> <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">sendAction</span>(block: <span style="color:#66d9ef">suspend</span> () <span style="color:#f92672">-></span> ACTION) </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">StateModule</span><STATE> : StateReceiver<STATE>, StateProvider<STATE> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">IntentModule</span><INTENT> : IntentReceiver<INTENT> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">ActionModule</span><ACTION> : ActionReceiver<ACTION>, ActionProvider<ACTION> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">MVIViewModel</span><STATE, INTENT, ACTION> : </span></span><span style="display:flex;"><span> StateModule<STATE>, </span></span><span style="display:flex;"><span> IntentModule<INTENT>, </span></span><span style="display:flex;"><span> ActionModule<ACTION> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MVIViewModelDelegate</span><STATE, INTENT, ACTION>( </span></span><span style="display:flex;"><span> initial: STATE </span></span><span style="display:flex;"><span>) : MVIViewModel<STATE, INTENT, ACTION> { </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">val</span> _state = MutableStateFlow(initial) </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">val</span> state: StateFlow<STATE> = _state.asStateFlow() </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">val</span> _action = Channel<ACTION>() </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">val</span> action: Flow<ACTION> = _action.receiveAsFlow() </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">suspend</span> <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">updateState</span>(transform: <span style="color:#66d9ef">suspend</span> (STATE) <span style="color:#f92672">-></span> STATE) { </span></span><span style="display:flex;"><span> _state.update { transform(<span style="color:#66d9ef">it</span>) } </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">suspend</span> <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">withState</span>(block: <span style="color:#66d9ef">suspend</span> (STATE) <span style="color:#f92672">-></span> Unit) { </span></span><span style="display:flex;"><span> block(_state.<span style="color:#66d9ef">value</span>) </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">suspend</span> <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">sendAction</span>(block: <span style="color:#66d9ef">suspend</span> () <span style="color:#f92672">-></span> ACTION) { </span></span><span style="display:flex;"><span> _action.trySend(block()) </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">override</span> <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">handleIntent</span>(intent: INTENT) { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">throw</span> NotImplementedError() </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span>}</span></span></code></pre></div> </div> </div> </main> </div> <footer class="footer"> <span>CC-0, Built with <a href="https://gohugo.io" class="footerLink">Hugo</a> and <a href="https://github.com/LordMathis/hugo-theme-nightfall" class="footerLink">Nightfall</a> theme</span> </footer> </div> </body> </html>