<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Michael Friend</title>
    <description>The latest articles on Forem by Michael Friend (@mrf7).</description>
    <link>https://forem.com/mrf7</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F384131%2F6fa27a48-346c-4378-ad9b-a5e005e184ac.jpeg</url>
      <title>Forem: Michael Friend</title>
      <link>https://forem.com/mrf7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mrf7"/>
    <language>en</language>
    <item>
      <title>Samples of Using KMMBridge</title>
      <dc:creator>Michael Friend</dc:creator>
      <pubDate>Wed, 30 Nov 2022 20:46:11 +0000</pubDate>
      <link>https://forem.com/touchlab/samples-of-using-kmmbridge-4bha</link>
      <guid>https://forem.com/touchlab/samples-of-using-kmmbridge-4bha</guid>
      <description>&lt;h2&gt;
  
  
  What is KMM Bridge?
&lt;/h2&gt;

&lt;p&gt;KMMBridge is a Gradle plugin by Touchlab that aims to simplify the process of pushing a Kotlin Multiplatform SDK binary to a remote repo to allow iOS developers to use the shared SDK without installing the Kotlin toolchain or building the Kotlin code on every app build.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is this Sample?
&lt;/h2&gt;

&lt;p&gt;This sample project showcases our typical project setup for adding Kotlin Multiplatform Mobile code to existing separate Android and iOS apps using KMMBridge. We keep the Android app and the shared code in the same repo and keep the code to an absolute minimum with no dependencies so the project will build faster to speed things up when playing around with custom publish config. To see how to set up a project that keeps the Android app in a separate repo and uses a more realistic structure in shared code, check out the article &lt;a href="https://touchlab.co/quick-start-with-kmmbridge-1-hour-tutorial/" rel="noopener noreferrer"&gt;Quickstart Guide to KMMBridge&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Repos
&lt;/h2&gt;

&lt;p&gt;The basic KMMBridge sample is split into four repos rather than being a monorepo to emulate the trend we've seen from teams adopting KMM into existing apps by publishing a KMM library from one repo for iOS apps in other repos to consume. &lt;br&gt;
The four repos are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/touchlab/KMMBridgeSampleKotlin" rel="noopener noreferrer"&gt;KMMBridgeSampleKotlin&lt;/a&gt; aka &lt;code&gt;Kotlin Repo&lt;/code&gt; - This is the Kotlin repo with the shared SDK code as well as an Android app that uses it. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/touchlab/KMMBridgeSampleCocoaPods" rel="noopener noreferrer"&gt;KMMBridgeSampleCocoaPods&lt;/a&gt; aka &lt;code&gt;CocoaPods Repo&lt;/code&gt;- a repo that pulls down the sdk with CocoaPods to use in an iOS app&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/touchlab/KMMBridgeSampleCocoaPods" rel="noopener noreferrer"&gt;KMMBridgeSampleSpm&lt;/a&gt; aka &lt;code&gt;SPM Repo&lt;/code&gt; - a repo that pulls down the sdk with Swift Package Manager to use in an iOS app&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/touchlab/PublicPodspecs" rel="noopener noreferrer"&gt;PublicPodspecs&lt;/a&gt; aka &lt;code&gt;Podspec Repo&lt;/code&gt; - A CocoaPods custom Podspec repo. When publishing for CocoaPods a podspec file will be pushed to this repo in a folder with the version number. See the CocoaPods section for more info on this. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  KMMBridgeSampleKotlin - The Kotlin Code
&lt;/h2&gt;

&lt;p&gt;This repo demonstrates the usual first step for a larger team that wants to try out Kotlin Multiplatform: putting new or existing Kotlin code in a &lt;code&gt;shared&lt;/code&gt; module in your Android app repo. This repo also has a standard Android &lt;code&gt;app&lt;/code&gt; module&lt;br&gt;
that depends on the shared code through a Gradle project dependency. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;shared&lt;/code&gt; module is a Kotlin Multiplatform module and targets &lt;code&gt;android&lt;/code&gt;, &lt;code&gt;ios&lt;/code&gt;, and &lt;code&gt;iosSimulatorArm64&lt;/code&gt;; declared in the &lt;code&gt;kotlin&lt;/code&gt; block of the &lt;code&gt;build.gradle.kts&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;kmmbridge&lt;/code&gt; config block, we set publishing both with both Swift Package Manager and Cocoapods. For your project you can just include one or the other based on your team's needs. It also uses &lt;code&gt;githubReleaseVersions&lt;/code&gt; to autoincrement versions when publishing a framework. Look over &lt;a href="https://touchlab.github.io/KMMBridge/general/CONFIGURATION_OVERVIEW" rel="noopener noreferrer"&gt;the docs&lt;/a&gt; for more configuration options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;addGithubPackagesRepository&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;kmmbridge&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;mavenPublishArtifacts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;githubReleaseVersions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;spm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;cocoapods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"git@github.com:touchlab/PublicPodspecs.git"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;versionPrefix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0.6"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Publishing Changes to Kotlin Code
&lt;/h3&gt;

&lt;p&gt;Since this publishes frameworks to our GitHub org, you'll need to fork the repo in order to publish changes. If you're only &lt;br&gt;
using SPM and remove the CocoaPods publishing, this should be enough to start publishing your changes. If you want to use &lt;br&gt;
CocoaPods you'll also need to fork the &lt;a href="https://github.com/touchlab/PublicPodspecs" rel="noopener noreferrer"&gt;Podspec Repo&lt;/a&gt; and change the URL passed to the &lt;code&gt;cocoapods(...)&lt;/code&gt; config above to your repo. You'll also have to set up deploy keys as secrets in your KMM repo. &lt;a href="https://touchlab.github.io/KMMBridge/cocoapods/COCOAPODS_GITHUB_PODSPEC" rel="noopener noreferrer"&gt;See Here&lt;/a&gt; for instructions on that.&lt;/p&gt;

&lt;p&gt;Once these steps are done you should be able to publish a new version of the SDK by manually running the publish job by going to the &lt;code&gt;Actions&lt;/code&gt; tab, selecting, &lt;code&gt;KMM Bridge Publish Release&lt;/code&gt; and clicking &lt;code&gt;Run workflow&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkhs02ire6fd1676cx6t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkhs02ire6fd1676cx6t.png" alt="run workflow" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Using KMM Code from iOS
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Configure Access
&lt;/h3&gt;

&lt;p&gt;To pull down the binary and build your iOS app you'll need to configure authentication with GitHub Packages. This can either be done in your &lt;code&gt;~/.netrc&lt;/code&gt; file or through Mac's Keychain Access.&lt;/p&gt;

&lt;p&gt;Either way you'll need to generate a GitHub Personal Access Token (PAT) with repo access and &lt;code&gt;read:packages&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bzkl9syvt0crnbe7rei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bzkl9syvt0crnbe7rei.png" alt="pataccess" width="800" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you get a PAT string from that, create or open &lt;code&gt;~/.netrc&lt;/code&gt; and add this with your username and the PAT that was created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;machine maven.pkg.github.com
  login &lt;span class="o"&gt;[&lt;/span&gt;your username]
  password &lt;span class="o"&gt;[&lt;/span&gt;your PAT]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to use Mac's keychain to manage access, check out &lt;a href="https://medium.com/geekculture/xcode-13-3-supports-spm-binary-dependency-in-private-github-release-8d60a47d5e45" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; for more details on setting that up.&lt;/p&gt;

&lt;h3&gt;
  
  
  SPM
&lt;/h3&gt;

&lt;p&gt;Since the base KMM repo is public, you should be able to clone &lt;a href="https://github.com/touchlab/KMMBridgeSampleSpm" rel="noopener noreferrer"&gt;the spm sample repo&lt;/a&gt; and run it. When you build the app it will look at the &lt;code&gt;Package.swift&lt;/code&gt; file in the root of the Kotlin module to get the url &lt;br&gt;
for the most recent version of the SDK then it will download the framework from that URL and include it in the project's build.&lt;/p&gt;
&lt;h4&gt;
  
  
  Getting Remote Changes
&lt;/h4&gt;

&lt;p&gt;To get changes to the Kotlin code you made in your fork of the repo, you'll have to change the SPM dependency to that repo.&lt;br&gt;
To do this first remove the existing dependency by selecting the project, clicking &lt;code&gt;Package Dependencies&lt;/code&gt;, clicking the package, and hitting the minus button. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60x7ioqcgw8pv5wkx8g7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60x7ioqcgw8pv5wkx8g7.png" alt="delete spm package" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, add your repo as a new dependency by clicking the plus button, pasting your repo URL in the search bar, and clicking &lt;br&gt;
&lt;code&gt;Add Package&lt;/code&gt;. Double-check the version rules to make sure it will grab the version you want.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkofi7d9r0ca53ffabxf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkofi7d9r0ca53ffabxf3.png" alt="add swift package" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've already run the publish job in the Kotlin repo, SPM should pull the SDK in with your changes, assuming you selected the version correctly. If you publish a new version and want to pull it, you can right-click &lt;code&gt;shared&lt;/code&gt; in the sidebar and click &lt;code&gt;Update Package&lt;/code&gt; &lt;br&gt;
to pull in the most recent version. &lt;/p&gt;

&lt;p&gt;If you want to build the Kotlin code locally and test in the iOS app without publishing every change, check out &lt;a href="https://touchlab.github.io/KMMBridge/spm/IOS_LOCAL_DEV_SPM" rel="noopener noreferrer"&gt;this document&lt;/a&gt; on the SPM local dev flow.&lt;/p&gt;
&lt;h3&gt;
  
  
  Cocoapods
&lt;/h3&gt;

&lt;p&gt;To run the CocoaPod based iOS app, clone &lt;a href="https://github.com/touchlab/KMMBridgeSampleCocoaPods.git" rel="noopener noreferrer"&gt;the sample repo&lt;/a&gt; and &lt;br&gt;
run &lt;code&gt;pod install&lt;/code&gt; in the root of the repo to download the SDK, then open the &lt;code&gt;xcworkspace&lt;/code&gt; file and run the app. &lt;code&gt;pod install&lt;/code&gt; will look in &lt;a href="https://github.com/touchlab/PublicPodspecs" rel="noopener noreferrer"&gt;https://github.com/touchlab/PublicPodspecs&lt;/a&gt; for a podspec matching the version specified in the &lt;code&gt;Podfile&lt;/code&gt; and &lt;br&gt;
download the framework it points to. &lt;/p&gt;
&lt;h4&gt;
  
  
  Getting Remote Changes
&lt;/h4&gt;

&lt;p&gt;To pull in changes you made to the Kotlin code with CocoaPods, you'll need to edit the &lt;code&gt;Podfile&lt;/code&gt; to point to the Podspec repo &lt;br&gt;
you created. Then run &lt;code&gt;pod update&lt;/code&gt; again and reopen your workspace file. We use &lt;code&gt;~&amp;gt; 0.6.0&lt;/code&gt; to tell CocoaPods to use the highest version above 0.6.0 up to but not including version 0.7.0. Since we set the version prefix to 0.6.0 in the &lt;code&gt;kmmbridge&lt;/code&gt; config and automatic versioning, every publish will get a new patch version for CocoaPods to recognize.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source '&amp;lt;YOUR PODSPEC REPO&amp;gt;'

target 'KMMBridgeSampleCocoaPods' do
  if ENV.include?("LOCAL_KOTLIN_PATH")
    pod 'shared', :path =&amp;gt; ENV["LOCAL_KOTLIN_PATH"]
  else
    pod 'shared', '~&amp;gt; 0.6.0'
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To build and test Kotlin changes locally with CocoaPods, check out &lt;a href="https://touchlab.github.io/KMMBridge/cocoapods/IOS_LOCAL_DEV_COCOAPODS" rel="noopener noreferrer"&gt;this doc&lt;/a&gt;&lt;br&gt;
on the CocoaPods local dev flow.&lt;/p&gt;

&lt;p&gt;If you have questions, don’t hesitate to reach out! You can head over to &lt;a href="https://kotlinlang.slack.com/archives/CTJB58X7X" rel="noopener noreferrer"&gt;#touchlab-tools&lt;/a&gt; on the kotlinlang Slack or fill out the &lt;a href="https://touchlab.co/contact-us/" rel="noopener noreferrer"&gt;Contact Us&lt;/a&gt; form on the site. We look forward to hearing from you!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Fun with Compose: Bad UI in a Great Framework</title>
      <dc:creator>Michael Friend</dc:creator>
      <pubDate>Fri, 30 Jul 2021 15:03:14 +0000</pubDate>
      <link>https://forem.com/touchlab/fun-with-compose-bad-ui-in-a-great-framework-1b43</link>
      <guid>https://forem.com/touchlab/fun-with-compose-bad-ui-in-a-great-framework-1b43</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;To celebrate Jetpack Compose finally hitting 1.0, I wanted to take a bit of a deep dive to see what the framework has to offer. Instead of more of the same code labs with useful UI, I decided to bring back an old reddit trend of creating the absolute worst volume control UI possible (&lt;a href="https://uxdesign.cc/the-worst-volume-control-ui-in-the-world-60713dc86950" rel="noopener noreferrer"&gt;highlights here&lt;/a&gt;). You can take a look at the code on my Github. &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mrf7" rel="noopener noreferrer"&gt;
        mrf7
      &lt;/a&gt; / &lt;a href="https://github.com/mrf7/volume-gore" rel="noopener noreferrer"&gt;
        volume-gore
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Microtransactions&lt;/th&gt;
&lt;th&gt;Radio Buttons&lt;/th&gt;
&lt;th&gt;Catapult (WIP)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://i.giphy.com/media/gCeelw0MJgkjCQ7fiF/giphy.gif"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://i.giphy.com/media/qbKWJdGpLOBxZvR70o/giphy.gif"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://i.giphy.com/media/VWD8QmlLT0h2Ymw2kW/giphy.gif"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Digits Of PI&lt;/th&gt;
&lt;th&gt;Seven Segment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://i.giphy.com/media/8h1loDBBTvdzGyI3Re/giphy.gif"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://i.giphy.com/media/dLYhwt8pRCIQPwu30m/giphy.gif"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;As someone who’s never really been a fan of UI work, building UI in Compose has been extremely pleasant and straightforward. Things like custom animations that I haven't done in the View system were surprisingly simple and concise. With Compose I no longer need to context switch between writing Kotlin code and XML layouts, the flow between writing backend code and UI code is much more seamless. The best part was the often lauded &lt;code&gt;LazyColumn&lt;/code&gt; in compose that turns 3 files worth of boilerplate &lt;code&gt;RecyclerView&lt;/code&gt; code into a couple lines. While it took some effort to change my approach for the Compose mental model, this is a huge leap in the right direction towards making UI work quicker for experienced devs and easier for new devs to learn. &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;A vital concept when learning Compose is how the runtime manages state and recomposition via &lt;code&gt;(Mutable)State&lt;/code&gt; objects. Most of the "magic" of recomposition relies on the &lt;code&gt;getValue&lt;/code&gt; and &lt;code&gt;setValue&lt;/code&gt; methods of these classes. and if you mistakenly go around these methods to read and update your apps state, you can actually prevent the UI from updating as you intended. &lt;/p&gt;

&lt;p&gt;I learned this the hard way while implementing the editable seven segment display by using a &lt;code&gt;MutableState&amp;lt;MutableList&amp;gt;&lt;/code&gt; and updating the underlying &lt;code&gt;MutableList&lt;/code&gt; values on user interaction (i.e. &lt;code&gt;state.value[index] = newValue&lt;/code&gt;). Desugaring that statement to &lt;code&gt;state.getValue()[index] = newValue&lt;/code&gt; we see that we're never calling &lt;code&gt;MutableState.setValue&lt;/code&gt;, so the Compose runtime has no indication of the underlying value change, never triggering a recomposition. On top of that, even if something else triggered a recomposition, the UI wouldn't be updated since we mutated the list without changing the reference, so the underlying equality check used to determine if our composable should run again  never detects a change.&lt;/p&gt;

&lt;p&gt;Luckily,Compose gives us a &lt;code&gt;mutableStateListOf(...)&lt;/code&gt; and &lt;code&gt;List.toMutableStateList()&lt;/code&gt; that return a &lt;code&gt;SnapshotStateList&lt;/code&gt;, which is a subclass of &lt;code&gt;MutableList&lt;/code&gt; (and equivalents for &lt;code&gt;Maps&lt;/code&gt;). That means we can just treat it as a  &lt;code&gt;MutableList&lt;/code&gt; and the state updates will be handled for us when we do things like &lt;code&gt;snapshotStateList[index]  = newValue&lt;/code&gt;. The main rule of thumb to learn from this is that in Compose you should avoid mutating objects you intend to use as a state and instead emit a brand new value to your LiveData/Flow/State using the &lt;code&gt;copy&lt;/code&gt; method on data classes. You can force this practice on yourself by avoiding &lt;code&gt;var&lt;/code&gt;s entirely in classes used for UI state. &lt;/p&gt;

&lt;p&gt;For a demonstration of this issue, here’s a snippet showing my initial &lt;code&gt;MutableList&lt;/code&gt; approach, a functional workaround I made using a list of mutable states, and the proper solution using &lt;code&gt;mutableStateListOf()&lt;/code&gt;. &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now that Compose is officially at 1.0, you should give it a shot ASAP. Wherever you update the state of your UI, keep an eye out for spots that mutate the value in the &lt;code&gt;State&lt;/code&gt; instead of the &lt;code&gt;State&lt;/code&gt; itself. Above all, don't be afraid to get creative and have fun when playing with compose, you might be surprised by the things you're able to make easily compared to the old View system. &lt;/p&gt;

</description>
      <category>android</category>
      <category>compose</category>
      <category>ux</category>
      <category>jetpackcompose</category>
    </item>
  </channel>
</rss>
