Thursday, Oct 5th 2023
- Moving on to state handling. And example todo app has some examples of state handling. Started creating custom store for storing user settings so I can create a settings page for the app.
- ChatGPT was again helpful in reminding how enum classes work in
Kotlin, what the
internal
visibility modifier means exactly, and how to type Composables that take other Composable as parameter (some lambda-wrapping was needed because@Composable
references are not supported out-of-the-box). - Noticed that Compose has a
@Preview
annotation for Composables that works with IDE to support showing a preview of the UI inside the IDE. But ... it's not supported for Multiplatform 🙄. There are reports that suggest you can get it working for the Android-only code, but if I'm targeting multiplatform that's kinda missing the point. - Text component is provided out-of-the-box by Compose (and works in Multiplatform as well), but couldn't find a standard dropdown selector. Googling found this example, so created a custom selector based on that.
- Storing user preferences is also something that needs to be manually
handled for each platform. Google provided some
examples,
and ChatGPT also, with a similar approach. However, both of these
failed to mention the Android-specific problem regarding
Context
s. More specifically, when working in the common, shared code, the context is not accessible at all, but it is required for some of the Android-specific functionality (such as storing preferences usinggetSharedPreferences()
). - Tried to work around the
Context
problem by using the@Composable
annotation. This works, since theContext
can be accessed from@Composable
functions when in Android-specific code by usingLocalContext.current
. But then the@Composable
-annotated functions cannot be called from any other scope (such as from inside a launched effect, or from a buttononClick
handler). And storing user preferences is anyway something that should not be a part of the@Composable
flow. - Finally gave up and used the late initialization techique described here. Now the Android library implementation gets the Application context on startup, and just uses that directly.
Thursday, Oct 5th 2023
- Aha! Compose seems to be built on top of a "single-Activity" mindset. It seems that others have also noticed that state handling was a pain with the previous model of firing up new Activities and having to recreate state from scratch. This is promising!
- Unfortunately again it seems that for Compose navigation is part of the standard library, but for Multiplatform the standard library is not working and you need to use external libraries.
- Trying out Appyx next for navigation.
Friday, Oct 6th 2023
- Started integrating Appyx by adding the dependencies
to the
implementation("com.bumble.appyx:appyx-navigation:2.0.0-alpha08") api("com.bumble.appyx:backstack:2.0.0-alpha08")
commonMain
source set. It seems that Appyx is about to release the 2.x version of their library, but since their site already lists the 2.x version and doesn't state that it should not yet be used, I'm gonna try it out even though it's alpha. - Started creating navigation based on the Quick start guide.
- Noticed that the code samples for the Desktop version seem to be out-of-date. No sense in banging my head against the wall here, since Desktop is not an interesting target for me.
- Dropped Desktop from the project.
- Noticed that running a full rebuild of the project (Rebuild Project from Android Studio) takes a really long time, like 5-10 minutes. Gradle also seems to get the caches broken if the Gradle build files are changed too much, especially when removing stuff or making larger changes to the project setup.
- To fix Gradle build, you may need to do any or all of the following:
- run cleanup script
./cleanup.sh
- clean project with
./gradlew clean
- clear user Gradle caches from e.g.
~/.gradle/caches
- invalidate IDE caches (Android Studio: File → Invalidate Caches)
- run cleanup script
- So, it turns out alpha versions of libraries can be uncooperative.
The appyx library seems promising but after a day of banging my head
to the wall I could not get the iOS version of the app to build. For
some reason the
Node
classes from the appyx library could not be found when building the iOS app. - Switched to Voyager and the basic navigation worked out-of-the-box.
Friday, Oct 6th 2023
Android Studio kept nagging me about Duplicate content roots detected. I did not feel like getting to know about this detail right now, so I just dumped the error message to ChatGPT, and pasted it a couple of my Gradle configuration files. This is an excerpt of ChatGPT's response:
Your project setup is for a Kotlin Multiplatform project that targets Android and iOS. Let's address the issue regarding the "Duplicate content roots detected".
From your shared build.gradle.kts:
android {
...
sourceSets["main"].resources.srcDirs("src/commonMain/resources")
...
}
This configuration tells Android's "main" source set to include src/commonMain/resources as its resource directory. However, Android Studio recognizes src/commonMain/resources as the resources directory for your Kotlin common source set by default.
This overlap between Android's "main" source set and Kotlin's "commonMain" source set is the source of your "Duplicate content roots detected" error.
To fix it: Remove the Overlap in shared/build.gradle.kts: Simply remove or comment out the line that adds src/commonMain/resources to Android's "main" source set.
...
Right! That did it. Man I'm glad I don't need to think myself anymore 🤯