arkivanov / essenty Goto Github PK
View Code? Open in Web Editor NEWThe most essential libraries for Kotlin Multiplatform development
License: Apache License 2.0
The most essential libraries for Kotlin Multiplatform development
License: Apache License 2.0
Shouldn't this return false if the backstack is empty or there is nothing for the backstack todo?
The latest version (0.7.0) shows the Parcelize annotation red with this error message: "Unresolved reference: Parcelize" in IntelliJ Ultimate 2022.3.1
This is NOT urgent as the project builds fine, just a little annoying.
Version 0.6.0 doesn't have this problem.
The current statekeeper implementation is pretty nice, espacially when using Decompose, however I think this feature should be supported.
Currently the StateKeeper has this method only
fun <T : Parcelable> register(key: String, supplier: () -> T?)
An additional (optional) onError method would be handy
fun <T : Parcelable> register(key: String, supplier: () -> T?, onError: (T?, Throwable) -> Unit)
To handle the exception and saving yourself.
E.g. some (Android) devices could throw a TooLargeException, so we could save it in a file for example as fallback
After upgrading to 0.4.0 from 0.3.1 compilation fails for target js with these kind of errors:
> No matching variant of com.arkivanov.essenty:lifecycle:0.4.0 was found. The consumer was configured to find a usage of 'kotlin-runtime' of a library, preferably optimized for non-jvm, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js', attribute 'org.jetbrains.kotlin.js.compiler' with value 'legacy' but:
- Variant 'commonMainMetadataElements' capability com.arkivanov.essenty:lifecycle:0.4.0 declares a library:
- Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
- Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
- Variant 'debugApiElements-published' capability com.arkivanov.essenty:lifecycle:0.4.0 declares a library:
- Incompatible because this component declares an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm' and the consumer needed a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
- Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
- Variant 'debugRuntimeElements-published' capability com.arkivanov.essenty:lifecycle:0.4.0 declares a runtime of a library:
- Incompatible because this component declares a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm' and the consumer needed a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
- Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
- Variant 'iosArm64ApiElements-published' capability com.arkivanov.essenty:lifecycle:0.4.0 declares a library:
- Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
- Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
- Variant 'iosArm64MetadataElements-published' capability com.arkivanov.essenty:lifecycle:0.4.0 declares a library:
- Incompatible because this component declares a usage of 'kotlin-metadata' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
- Other compatible attributes:
- Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
- Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
- Variant 'iosSimulatorArm64ApiElements-published' capability com.arkivanov.essenty:lifecycle:0.4.0 declares a library:
and so on
When I remove js from my app (leaving jvm, Android and iOS) it compiles without issues.
In Common code of Compose Multiplatform,
I have the below code.
LaunchedEffect("LifeCycle"){
val callbacks: Lifecycle.Callbacks =
object : Lifecycle.Callbacks {
override fun onCreate() {
}
override fun onStart() {
}
override fun onResume() {
}
override fun onPause() {
Logger.i (messageString = "Home Screen LaunchedEffect onPause", tag = "Home")
}
override fun onStop() {
Logger.i (messageString = "Home Screen LaunchedEffect onStop", tag = "Home")
}
override fun onDestroy() {
}
}
viewModel.lifeCycleCallBack = callbacks
mAppLifeCycleOwner.lifecycle.subscribe(callbacks)
Logger.i (messageString = "Home Screen LaunchedEffect lifeCycleCallBack register", tag = "Home")
}
I does not trigger, I am testing it with Android for now, May be I am missing something...
I am also try below as well
private var mlifecycle :LifecycleRegistry = LifecycleRegistry(initialState = Lifecycle.State.INITIALIZED)
In my Android Native activity.
override fun onStop() {
super.onStop()
mlifecycle.onStop()
Logger.i (messageString = "onStop", tag = "MainActivity")
}
This should be placed in the parcelable module.
See the discussion #47.
Here is a tentative implementation from the discussion:
// Parceler.kt in commonMain
expect interface Parceler<T>
// WriteWith.kt in commonMain
@OptIn(ExperimentalMultiplatform::class)
@OptionalExpectation
@Target(AnnotationTarget.TYPE)
expect annotation class WriteWith<P : Parceler<*>>()
// Parceler.kt in androidMain
actual typealias Parceler<T> = kotlinx.parcelize.Parceler<T>
// WriteWith.kt in androidMain
actual typealias WriteWith<P> = kotlinx.parcelize.WriteWith<P>
// Parceler.kt in nonAndroidMain
actual interface Parceler<T>
file:///Users/shubham.garg/Downloads/Android-SDK-Sample-App-main/payu-sdk/src/commonMain/kotlin/com/payu/india/Model/Bnpl.kt:9:6 Class 'Bnpl' is not abstract and does not implement abstract member public abstract fun describeContents(): Int defined in android.os.Parcelable
Exception on building project, js target:
./gradlew :composeApp:jsBrowserDevelopmentRun
e: Could not find "Essenty:lifecycle" in [C:\Users\User\AppData\Local\kotlin\daemon]
e: java.lang.IllegalStateException: FATAL ERROR: Could not find "Essenty:lifecycle" in [C:\Users\User\AppData\Local\kotlin\daemon]
versions
kotlin = "1.8.20"
compose = "1.4.0"
kotlinx-coroutines = "1.6.4"
decompose = "1.0.0"
mvikotlin = "3.0.2"
essenty = "1.1.0"
kotlinx-serialization = "1.5.1"
"com.arkivanov.decompose:extensions-compose-jetbrains:1.0.0-compose-experimental"
"com.arkivanov.decompose:extensions-compose-jetbrains:1.0.0-beta-04-native-compose"
kotlin version: 1.8.20
error message: java.lang.IllegalStateException: FATAL ERROR: Could not find "Essenty:lifecycle" in [C:\Users\User\AppData\Local\kotlin\daemon]
at org.jetbrains.kotlin.ir.backend.js.KlibKt$resolverLogger$1.fatal(klib.kt:111)
at org.jetbrains.kotlin.library.KotlinLibrarySearchPathResolver.resolve(SearchPathResolver.kt:171)
at org.jetbrains.kotlin.library.SearchPathResolver.resolve$default(SearchPathResolver.kt:20)
at org.jetbrains.kotlin.library.SearchPathResolverKt.resolve(SearchPathResolver.kt:29)
at org.jetbrains.kotlin.library.metadata.resolver.impl.KotlinLibraryResolverImpl$resolveDependencies$2$2.invoke(KotlinLibraryResolverImpl.kt:122)
at org.jetbrains.kotlin.library.metadata.resolver.impl.KotlinLibraryResolverImpl$resolveDependencies$2$2.invoke(KotlinLibraryResolverImpl.kt:122)
at kotlin.sequences.TransformingSequence$iterator$1.next(Sequences.kt:210)
at kotlin.sequences.FilteringSequence$iterator$1.calcNext(Sequences.kt:170)
at kotlin.sequences.FilteringSequence$iterator$1.hasNext(Sequences.kt:194)
at kotlin.sequences.TransformingSequence$iterator$1.hasNext(Sequences.kt:214)
at kotlin.sequences.FilteringSequence$iterator$1.calcNext(Sequences.kt:169)
at kotlin.sequences.FilteringSequence$iterator$1.hasNext(Sequences.kt:194)
at kotlin.sequences.SequencesKt___SequencesKt.toCollection(_Sequences.kt:787)
at kotlin.sequences.SequencesKt___SequencesKt.toMutableList(_Sequences.kt:817)
at kotlin.sequences.SequencesKt___SequencesKt.toList(_Sequences.kt:808)
at org.jetbrains.kotlin.library.metadata.resolver.impl.KotlinLibraryResolverImpl.resolveDependencies(KotlinLibraryResolverImpl.kt:135)
at org.jetbrains.kotlin.library.metadata.resolver.impl.KotlinLibraryResolverImpl.resolveWithDependencies(KotlinLibraryResolverImpl.kt:44)
at org.jetbrains.kotlin.ir.backend.js.JsLibraryResolverKt.jsResolveLibraries(JsLibraryResolver.kt:51)
at org.jetbrains.kotlin.ir.backend.js.ModulesStructure.<init>(klib.kt:476)
at org.jetbrains.kotlin.ir.backend.js.PrepareAnalyzedSourceModuleKt.prepareAnalyzedSourceModule(prepareAnalyzedSourceModule.kt:26)
at org.jetbrains.kotlin.ir.backend.js.PrepareAnalyzedSourceModuleKt.prepareAnalyzedSourceModule$default(prepareAnalyzedSourceModule.kt:16)
at org.jetbrains.kotlin.cli.js.K2JsIrCompiler.processSourceModule(K2JsIrCompiler.kt:435)
at org.jetbrains.kotlin.cli.js.K2JsIrCompiler.doExecute(K2JsIrCompiler.kt:295)
at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:180)
at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:72)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:100)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:46)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
at org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner.runCompiler(IncrementalJsCompilerRunner.kt:213)
at org.jetbrains.kotlin.incremental.IncrementalJsCompilerRunner.runCompiler(IncrementalJsCompilerRunner.kt:84)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:486)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:409)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileNonIncrementally(IncrementalCompilerRunner.kt:290)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:112)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile$default(IncrementalCompilerRunner.kt:94)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execJsIncrementalCompiler(CompileServiceImpl.kt:567)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execJsIncrementalCompiler(CompileServiceImpl.kt:101)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1678)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Project with reproduction:
https://github.com/t1r/ComposeThemeBuilder/tree/gradle_rework
branch - gradle_rework
It looks like androidx lifecycle supports KMP now.
https://developer.android.com/jetpack/androidx/releases/lifecycle#2.8.0-alpha02
The core Lifecycle APIs in Lifecycle, LifecycleOwner, LifecycleObserver, Lifecycle.State, Lifecycle.Event, and LifecycleRegistry are now shipped in artifacts compatible with Kotlin Multiplatform.
For desktop apps that don't need to use Decompose, but want to use Essenty for lifecycle handling, having LifecycleController in the Decompose introduces unnecessary overhead of depending on the whole library just for the lifecycle functionality. Consider moving functionality that allows to provide Essenty lifecycle for desktop, compose and other platforms to a separate module in Essenty instead of Decompose.
With K2 compiler coming it would be good to make this library work with it too. Right now I'm getting this error:
Class SomeParcelableClass is not abstract and does not implement abstract member describeContents
K2 compiler enabled via kotlin.experimental.tryK2=true
in gradle.properties
StateKeeper
makes a bit redundantly strong contract for supplier imo, requiring non-optional Parcelable
from supplier (here).
Simply put, we have
interface StateKeeper {
...
fun <T : Parcelable> register(key: String, supplier: () -> T)
...
}
And I want
interface StateKeeper {
...
fun <T : Parcelable?> register(key: String, supplier: () -> T)
...
}
Note the T : Parcelable?
part.
Maybe I'm not seeing the reason behind the non-nullable contract, please correct me if I'm wrong.
I have an abstract class that I want to write a custom Parceler
for per https://developer.android.com/kotlin/parcelize
e.g.
@Parcelize
data class User(val firstName: String, val lastName: String, val age: Int) : Parcelable {
private companion object : Parceler<User> {
override fun User.write(parcel: Parcel, flags: Int) {
// Custom write implementation
}
override fun create(parcel: Parcel): User {
// Custom read implementation
}
}
}
Cheers.
Good day!
Extension function InstanceKeeper.getOrCreate(...)
provides convenient way to get value from InstanceKeeper
or create it otherwise.
It would be very useful to add similar function for StateKeeper
to allow receive saved value from StateKeeper
(if any) and at the same time register supplier
that will provide value to save.
It will have the following benefits:
key
will be specified once only, less copy-paste typossupplier
will provide value of the same type that is consumed from StateKeeper
for the same key
supplier
is provided, so it will be harder to forget to register itThe function may be implemented as the following (name could be better):
inline fun <reified T : Parcelable> StateKeeper.registerAndConsume(key: String, noinline supplier: () -> T): T? {
register(key, supplier)
return consume(key)
}
And usage looks like:
class SomeValue : Parcelable
val someValue: SomeValue? = stateKeeper.registerAndConsume("some_key") { SomeValue() }
I can create PR, if needed.
Can be useful with deelinks.
Hey,
I'm using Essenty
in one of my KMM projects and I noticed that TypeParceler
and IgnoredOnParcel
are not available in published artifact.
Can be replicated running version 0.6.0, with new KMM project, Kotlin 1.7.10.
This function is needed to develop custom integrations with Essenty for other libraries that want to provide the same default values for certain APIs as decompose does. For example, creating a function analogous to
fun LifecycleOwner.coroutineScope(
context: CoroutineContext = Dispatchers.Main.immediateOrFallback,
): CoroutineScope =
CoroutineScope(context = context).withLifecycle(lifecycle)
Is impossible right now because the default value cannot be retrieved.
Our use-case is such that we want to provide a retained coroutine scope that uses immediate dispatcher by default and we cannot do that unless we copy and paste the code from Essenty.
This is a very promising library. So far, I haven't been able to figure out how to use it for my Kotlin Multiplatform project.
My only real requirement is to run a OnResume function to update my main activity, when it is brought back into focus from background.
I am not clear where to instantiate the functions:
val lifecycleRegistry = LifecycleRegistry()
val someLogic = SomeLogic(lifecycleRegistry)
Do I need to call lifecycleRegistry.subscribe()
from the Composable of the activity in question?
What I'm currently doing in my main module is define the SomeLogic class:
class SomeLogic(lifecycle: Lifecycle,t:MutableState<String>) {
init {
lifecycle.subscribe(
onResume = {t.value="Res1"}
)
lifecycle.doOnResume {
t.value = "Res";
}
}
}
then instantiate the members in the Composable of the main activity:
The OnResume function is however never called.
val lifecycleRegistry = LifecycleRegistry()
val someLogic = SomeLogic(lifecycleRegistry,t3)
lifecycleRegistry.subscribe()
lifecycleRegistry.doOnCreate { t3.value="yo" }
The OnResume function is however never called.
Any advice or reference to sample projects would be highly appreciated.
Android 6 (23)
Caused by java.util.zip.ZipException: Entry is not named
at java.util.zip.ZipInputStream.getNextEntry([ZipInputStream.java:268](https://zipinputstream.java:268/))
at com.arkivanov.essenty.statekeeper.Utils_javaKt.deserialize(Utils.java.kt:1)
at com.arkivanov.essenty.statekeeper.AndroidExtKt.StateKeeper(AndroidExt.kt:1)
at com.arkivanov.essenty.statekeeper.AndroidExtKt.stateKeeper(AndroidExt.kt:1)
at com.arkivanov.decompose.DefaultComponentContextBuilderKt.defaultComponentContext(DefaultComponentContextBuilder.kt:1)
at com.arkivanov.decompose.DefaultComponentContextBuilderKt.defaultComponentContext(DefaultComponentContextBuilder.kt:1)
at com.arkivanov.decompose.DefaultComponentContextBuilderKt.defaultComponentContext$default(DefaultComponentContextBuilder.kt:1)
Hi, I have a generic parameter in a child class of a Sealed Class in Common Module.
Generally if I had to parcelize this parameter in Android Module then I would have the @RawValue
annotation coming from kotlinx.parcelize.RawValue
. Is there any annotation provided by this library which can help me do the same?
My Sealed Class
import com.arkivanov.essenty.parcelable.Parcelable
import com.arkivanov.essenty.parcelable.Parcelize
/**
* Generic class which can be used to describe the state of a screen
*/
@Parcelize
sealed class UIState<out T> : Parcelable {
object Empty : UIState<Nothing>()
object Loading : UIState<Nothing>()
@Parcelize
class Success<T>(val data: T) : UIState<T>()
class Error(val exception: Exception) : UIState<Nothing>()
}
Getting this error for the data
variable of Success
class which is of type T
:
Type is not directly supported by 'Parcelize'. Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'
The version 1.5.10-beta01 of compose added UIViewController lifetime hooks (see JetBrains/compose-multiplatform-core#779)
It is possible to do similar thing for essenty??
The current API of BackPressedHandler
and BackPressedDispatcher
is not compatible with the new predictive back gesture on Android 13. When this mode is enabled and there is a callback registered in BackPressedHandler
, the predictive back gesture just doesn't work and the back gesture works in the old-fashioned way.
The point of this task is to update the existing API or introduce a new one compatible with the new behaviour.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.