Olivier Patry
03/19/2021, 2:03 PMvectorXmlResource but it fails with a NPE, form openResourceStream. I guess my problem comes from my Gradle configuration not packaging my assets in the final Jar file but I don't know how to fix that. Any clue?
desktop-app/src/main/kotlin for the source code, desktop-app/src/main/resources for the assets. I put an icons/ dir within resources/ which contains my Android Vector drawables and then I use vectorXmlResource("icons/ic_settings.xml").Olivier Patry
03/19/2021, 2:03 PMdesktop-app/build.gradle.kts
import org.jetbrains.compose.compose
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm")
id("org.jetbrains.compose")
application
}
group = "org.acme"
version = "1.0.0"
dependencies {
implementation(compose.desktop.currentOs)
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
application {
mainClass.set("MainKt")
}Olivier Patry
03/19/2021, 2:04 PMresources/ dir as an assets directory)Igor Demin
03/19/2021, 4:39 PMOlivier Patry
03/19/2021, 5:22 PMOlivier Patry
03/19/2021, 5:44 PMModifier.size(48.dp) make the crash easier but even without that, I have random crashes.
If Iaunch it several times in sequence…Olivier Patry
03/19/2021, 5:58 PMModifier.size(48.dp)Igor Demin
03/19/2021, 6:13 PMThread.currentThread().contextClassLoader
Maybe something somewhere overrides it?
Try to call this before `vectorXmlResource`:
Thread.currentThread().contextClassLoader = ClassLoader.getSystemClassLoader()
(just to be sure that this is because of contextClassLoader)Olivier Patry
03/19/2021, 6:30 PMOlivier Patry
03/19/2021, 6:30 PMOlivier Patry
03/19/2021, 6:30 PMOlivier Patry
03/19/2021, 6:31 PMIgor Demin
03/19/2021, 6:44 PMI'm surprised, Compose runtime is multithreaded?It is single threaded for now, but there are plans to make it multi-threaded.
this as a bug on Compose side or should I manage this on my sideI think we can replace
Thread.currentThread().contextClassLoader by ClassLoader.getSystemClassLoader() in Compose (we just need to be sure that everything will work as before).
You also can manage this on your side, if somewhere in your code contextClassLoader is changed. Usually we need to override contextClassLoader only for some part of the code and then revert it:
val contextClassLoader = Thread.currentThread().contextClassLoader
try {
Thread.currentThread().contextClassLoader = ...
...
} finally {
Thread.currentThread().contextClassLoader = contextClassLoader
}
Things get complicated if some third-party library changes it and forgets to revert.Olivier Patry
03/19/2021, 7:07 PMOlivier Patry
03/19/2021, 7:13 PMExecutors.newSingleThreadExecutor() but all of this is wrapped using suspendCoroutine {}
In other circumstances, such background tasks invokes callback on their thread which I delegate to a view model class which itself updates a MutableStateFlow with MainScope coroutine scope
private val viewModelScope: CoroutineScope = MainScope()
private val _collections = MutableStateFlow<LibraryState>(LibraryState.Unloaded)
val collections: Flow<LibraryState>
get() = _collections
.... something called from background ....
viewModelScope.launch(context = Dispatchers.Main) {
_collections.value = LibraryState.Updated(collectionModels)
}
....
Then, on compose side
val state by libraryViewModel.collections.collectAsState(LibraryState.Unloaded)
So maybe this setup leads to odd behavior?Olivier Patry
03/19/2021, 7:16 PMTry catch is not supported around composable function invocations.I'll do it another way
Olivier Patry
03/20/2021, 10:05 AMcollectAsState recomposition comes from a native library.
I know, on Android, there are some oddities with class loaders and JNI for threads created from native side.
Maybe it's something linked to this too on desktop?Igor Demin
03/20/2021, 10:13 AMMaybe it's something linked to this too on desktop?Yes, threads created from native side have no
contextClassLoader.
Do you control the code which is called from native side?
You can call Thread.currentThread().contextClassLoader = ClassLoader.getSystemClassLoader() there, not in Composable function.Olivier Patry
03/20/2021, 10:21 PMicon helper, I'll do the trick here for now.
There are to much code being called from native callbacks right now.
Thanks 👍