Vadim Kapustin
11/18/2020, 11:32 AMIcon(imageFromResource("images/logo.png"))
But sometimes, when the system is under heavy load I have NullPointerException in DesktopImageAssetKt.loadResource()
Apparently the icon doesn't have time to load...
How to make waiting for the icon to load and then display it?Igor Demin
11/18/2020, 12:02 PMimageFromResource
shouldn't be used directly in @Composable
function.
Use imageResource
instead (it loads resource only in the first call of Composable
function)
But NullPointerException
looks strange. Loading and composition here is synchronous in a single thread, so theoretically everything should work.
Also strange that Icon
sometimes works.
Icon
shouldn't work with "png" images, it will show black rectangle instead of an image.
For "png" images we should use Image
Vadim Kapustin
11/18/2020, 12:33 PMimageFromResource
to imageResource
and tried to repeat situation with NullPointerException
, all works well...Exception in thread "AWT-EventQueue-0 @coroutine#1" java.lang.NullPointerException
at androidx.compose.ui.graphics.DesktopImageAssetKt.loadResource(DesktopImageAsset.kt:80)
Igor Demin
11/18/2020, 2:00 PMval resource = Thread.currentThread().contextClassLoader.getResource(path)
Maybe something overrides contextClassLoader in your application 🤔. Is it pure "Compose" application?
Also it will be very helpful if you can provide a snippet with bugVadim Kapustin
11/18/2020, 2:30 PM@Composable
override fun render() {
HintContainer {
Scaffold(
topBar = { infoBar.render() }
) {
//...
infoBar render contains StatusIcon:
@Composable
override fun render() {
val connectionState = remember { databaseController.connectionStatus }.collectAsState()
TopAppBar {
val connectMessage = derivedStateOf {
when (connectionState.value) {
ConnectionStatus.INITIALIZED -> "Connecting to database"
ConnectionStatus.SUCCESS -> "Connected to ${databaseController.connection}"
else -> "Failed connection"
}
}
val statusColor = derivedStateOf {
if (connectionState.value == ConnectionStatus.SUCCESS) Color.Unspecified
else AppTheme.colors.material.error
}
Row(modifier = Modifier.weight(1f)) {
StatusIcon(
message = connectMessage.value,
color = statusColor.value,
modifier = Modifier.align(Alignment.CenterVertically).padding(8.dp)
)
// .....
connectionStatus described in databaseController:
private val _state = MutableStateFlow<ConnectionStatus>(ConnectionStatus.NOT_REQUESTED)
val connectionStatus: StateFlow<ConnectionStatus> get() = _state
_state.value changes in another coroutine
I hope this information will be enoughException happened in this line?
val resource = Thread.currentThread().contextClassLoader.getResource(path)Yes
Igor Demin
11/20/2020, 5:01 PM@Composable
fun imageResource2(path: String): ImageBitmap {
return remember(path) { Image.makeFromEncoded(loadResource2(path)).asImageBitmap() }
}
private fun loadResource2(path: String): ByteArray {
val resource = ClassLoader.getSystemClassLoader().getResource(path)
requireNotNull(resource) { "Resource $path not found" }
return resource.readBytes()
}
Also maybe on the latest version (0.2.0-build128) it will be working?
We changed default coroutine dispatcher recently (https://github.com/JetBrains/compose-jb/issues/17)Vadim Kapustin
11/23/2020, 6:22 PMIgor Demin
11/23/2020, 6:24 PM