The most essential libraries for Kotlin Multiplatform development

Related tags

Kotlin Essenty
Overview

Maven Central License Twitter URL

Essenty

The most essential libraries for Kotlin Multiplatform development.

Supported targets:

  • android
  • jvm
  • js (IR and LEGACY)
  • iosArm64, iosX64
  • watchosArm32, watchosArm64, watchosX64
  • tvosArm64, tvosX64
  • macosX64
  • linuxX64

Lifecyle

When writing Kotlin Multiplatform (common) code we often need to handle lifecycle events of a screen. For example, to stop background operations when the screen is destroyed, or to reload some data when the screen is activated. Essenty provides the Lifecycle API to help with lifecycle handling in the common code. It is very similar to Android Activity lifecycle.

Setup

Groovy:

// Add the dependency, typically under the commonMain source set
implementation "com.arkivanov.essenty:lifecycle:<essenty_version>"

Kotlin:

// Add the dependency, typically under the commonMain source set
implementation("com.arkivanov.essenty:lifecycle:<essenty_version>")

Lifecycle state transitions

Content

The main Lifecycle interface provides ability to observe the lifecycle state changes.

The LifecycleRegistry interface extends both the Lifecycle and the Lifecycle.Callbacks at the same time. It can be used to manually control the lifecycle, for example in tests.

The LifecycleOwner just holds the Lifecyle. It may be implemented by an arbitrary class, to provide convenient API.

Android extensions

From Android, the Lifecycle can be obtained by using special functions, can be found here.

Usage example

The lifecycle can be observed using its subscribe/unsubscribe methods:

import com.arkivanov.essenty.lifecycle.Lifecycle

class SomeLogic(lifecycle: Lifecycle) {
    init {
        lifecycle.subscribe(
            object : Lifecycle.Callbacks {
                override fun onCreate() {
                    // Handle lifecycle created
                }

                // onStart, onResume, onPause, onStop are also available

                override fun onDestroy() {
                    // Handle lifecycle destroyed
                }
            }
        )
    }
}

Or using the extension functions:

import com.arkivanov.essenty.lifecycle.Lifecycle
import com.arkivanov.essenty.lifecycle.doOnCreate
import com.arkivanov.essenty.lifecycle.doOnDestroy
import com.arkivanov.essenty.lifecycle.subscribe

class SomeLogic(lifecycle: Lifecycle) {
    init {
        lifecycle.subscribe(
            onCreate = { /* Handle lifecycle created */ },
            // onStart, onResume, onPause, onStop are also available
            onDestroy = { /* Handle lifecycle destroyed */ }
        )

        lifecycle.doOnCreate {
            // Handle lifecycle created
        }

        // doOnStart, doOnResume, doOnPause, doOnStop are also available

        lifecycle.doOnDestroy {
            // Handle lifecycle destroyed
        }
    }
}

Parcelable and Parcelize

Essenty brings both Android Parcelable interface and the @Parcelize annotation from kotlin-parcelize compiler plugin to Kotlin Multiplatform, so they both can be used in common code. This is typically used for state/data preservation over Android configuration changes, when writing common code targeting Android.

Setup

Groovy:

plugins {
    id "kotlin-parcelize" // Apply the plugin for Android
}

// Add the dependency, typically under the commonMain source set
implementation "com.arkivanov.essenty:parcelable:<essenty_version>"

Kotlin:

plugins {
    id("kotlin-parcelize") // Apply the plugin for Android
}

// Add the dependency, typically under the commonMain source set
implementation("com.arkivanov.essenty:parcelable:<essenty_version>")

Usage example

Once the dependency is added and the plugin is applied, we can use it as follows:

import com.arkivanov.essenty.parcelable.Parcelable
import com.arkivanov.essenty.parcelable.Parcelize

@Parcelize
data class User(
    val id: Long,
    val name: String
) : Parcelable

When compiled for Android, the Parcelable implementation will be generated automatically. When compiled for other targets, it will be just a regular class without any extra generated code.

Parcelize for Darwin/Apple targets

Currently there is no extra code generated when compiled for Darwin/Apple targets. However I made a proof of concept: kotlin-parcelize-darwin compiler plugin. It is not used yet by Essenty, and the applicabilty is being considered. Please raise a Discussion if you are interested.

StateKeeper

When writing common code targetting Android, it might be required to preserve some data over Android configuration changes or process death. For this purpose, Essenty provides the StateKeeper API, which is inspired by the AndroidX SavedStateHandle. The StateKeeper API relies on the Parcelable interface provided by the parcelable module described above.

Setup

Groovy:

// Add the dependency, typically under the commonMain source set
implementation "com.arkivanov.essenty:state-keeper:<essenty_version>"

Kotlin:

// Add the dependency, typically under the commonMain source set
implementation("com.arkivanov.essenty:state-keeper:<essenty_version>")

Content

The main StateKeeper interface provides ability to register/unregister state suppliers, and also to consume any previously saved state.

The StateKeeperDispatcher interface extens StateKeeper and allows state saving, by calling all registered state providers.

The StateKeeperOwner interface is just a holder of StateKeeper. It may be implemented by an arbitrary class, to provide convenient API.

Android extensions

From Android side, StateKeeper can be obtained by using special functions, can be found here.

Usage example

import com.arkivanov.essenty.parcelable.Parcelable
import com.arkivanov.essenty.parcelable.Parcelize
import com.arkivanov.essenty.statekeeper.StateKeeper
import com.arkivanov.essenty.statekeeper.consume

class SomeLogic(stateKeeper: StateKeeper) {
    // Use the saved State if any, otherwise create a new State
    private var state: State = stateKeeper.consume("SAVED_STATE") ?: State()

    init {
        // Register the State supplier
        stateKeeper.register("SAVED_STATE") { state }
    }

    @Parcelize
    private class State(
        val someValue: Int = 0
    ) : Parcelable
}

InstanceKeeper

When writing common code targetting Android, it might be required to retain objects over Android configuration changes. This use case is covered by the InstanceKeeper API, which is similar to the AndroidX ViewModel.

Setup

Groovy:

// Add the dependency, typically under the commonMain source set
implementation "com.arkivanov.essenty:instance-keeper:<essenty_version>"

Kotlin:

// Add the dependency, typically under the commonMain source set
implementation("com.arkivanov.essenty:instance-keeper:<essenty_version>")

Content

The main InstanceKeeper interface is responsible for storing object instances, represented by the [InstanceKeeper.Instance] interface. Instances of the InstanceKeeper.Instance interface survive Android Configuration changes, the InstanceKeeper.Instance.onDestroy() method is called when InstanceKeeper goes out of scope (e.g. the screen is finished).

The InstanceKeeperDispatcher interface extens InstanceKeeper and adds ability to destroy all registered instances.

The InstanceKeeperOwner interface is just a holder of InstanceKeeper. It may be implemented by an arbitrary class, to provide convenient API.

Android extensions

From Android side, InstanceKeeper can be obtained by using special functions, can be found here.

Usage example

import com.arkivanov.essenty.instancekeeper.InstanceKeeper
import com.arkivanov.essenty.instancekeeper.getOrCreate

class SomeLogic(instanceKeeper: InstanceKeeper) {
    // Get the existing instance or create a new one
    private val thing: RetainedThing = instanceKeeper.getOrCreate { RetainedThing() }
}

/*
 * Survives Android configuration changes.
 * ⚠️ Pay attention to not leak any dependencies.
 */
class RetainedThing : InstanceKeeper.Instance {
    override fun onDestroy() {
        // Called when the screen is finished
    }
}

BackPressedDispatcher

The BackPressedDispatcher API provides ability to handle back button clicks (e.g. an Android device's back button), in common code. This API is similar to AndroidX OnBackPressedDispatcher.

Setup

Groovy:

// Add the dependency, typically under the commonMain source set
implementation "com.arkivanov.essenty:back-pressed:<essenty_version>"

Kotlin:

// Add the dependency, typically under the commonMain source set
implementation("com.arkivanov.essenty:back-pressed:<essenty_version>")

Content

The BackPressedHandler interface provides ability to register/unregister back button handlers. When the device's back button is clicked, all registered handlers are called in reverse order. If a handler returns true then the event is considered as handled and the handling process stops, the remaining handlers are not called. If none of the handlers returned true then the event is considered as unhandled.

The BackPressedDispatcher interface extends BackPressedHandler and is responsible for triggering the registered handlers. The BackPressedDispatcher.onBackPressed() triggers all registered handlers in reverse order, returns true if the event is handled, and false if the event is unhandled.

Android extensions

From Android side, BackPressedDispatcher can be obtained by using special functions, can be found here.

Usage example

TBD

Author

Twitter: @arkann1985

If you like this project you can always Buy Me A Coffee ;-)

Comments
  • Unresolved reference: Parcelize

    Unresolved reference: Parcelize

    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.

    bug 
    opened by DATL4G 9
  • Upgrade to 0.4.0 removes support for js target

    Upgrade to 0.4.0 removes support for js target

    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.

    bug 
    opened by 1gravity 8
  • Utility function for StateKeeper

    Utility function for StateKeeper

    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 typos
    • it will ensure that supplier will provide value of the same type that is consumed from StateKeeper for the same key
    • it will ensure that supplier is provided, so it will be harder to forget to register it

    The 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.

    opened by qwert2603 8
  • Custom Parcelers

    Custom Parcelers

    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.

    opened by gnawf 5
  • TypeParceler is missing in `Parcelable` artifact

    TypeParceler is missing in `Parcelable` artifact

    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.

    opened by krizzu 2
  • Update Parcelize annotations

    Update Parcelize annotations

    • Added @TypeParceler
    • ~~Added @RawValue~~
    • Moved @WriteWith to its own file
    • Applied @OptionalExpectation to @Parcelize and removed actual implementation from nonAndroidMain
    opened by vganin 2
  • `BackPressedDispatcher.onBackPressed()` always returns true

    `BackPressedDispatcher.onBackPressed()` always returns true

    https://github.com/arkivanov/Essenty/blob/master/back-pressed/src/androidMain/kotlin/com/arkivanov/essenty/backpressed/AndroidExt.kt#L59-L65

    Shouldn't this return false if the backstack is empty or there is nothing for the backstack todo?

    question 
    opened by ScottPierce 2
  • Support optional values in StateKeeper's supplier

    Support optional values in StateKeeper's supplier

    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.

    enhancement 
    opened by vganin 1
  • Add Parceler and WriteWith

    Add Parceler and WriteWith

    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>
    
    enhancement 
    opened by arkivanov 1
  • Comply with the new predictive back gesture on Android 13

    Comply with the new predictive back gesture on Android 13

    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.

    enhancement 
    opened by arkivanov 0
Releases(0.8.0)
  • 0.8.0(Jan 1, 2023)

    • Parcelable extends Serializable on JVM (#81)

    Parcelable for JVM targets (experimental)

    Now Parcelable interface extends java.io.Serializable on JVM. This makes it possible to serialize and deserialize Parcelable classes as ByteArray using ObjectOutputStream and ObjectInputStream.

    Versions and dependencies

    Kotlin: 1.7.21 parcelize-darwin: 0.1.2

    Source code(tar.gz)
    Source code(zip)
  • 0.7.1(Dec 25, 2022)

    • Replaced all @OptionalExpectation annotations with actual no-op implementations for non-Android targets (#80, fixes #79)

    Versions and dependencies

    Kotlin: 1.7.21 parcelize-darwin: 0.1.2

    Source code(tar.gz)
    Source code(zip)
  • 0.7.0(Dec 15, 2022)

    • Updated Kotlin to 1.7.21 (#75)
    • Added isDestroyed check to InstanceKeeperDispatcher (#70 by @VladislavSumin)
    • Parcelize: added @IgnoredOnParcel annotation (#72 by @vganin)
    • Parcelize: added @TypeParceler and @WriteWith annotations (#73 by @vganin)
    • Parcelize: applied parcelize-darwin plugin (#76)

    The new parcelize-darwin plugin

    This release adds an experimental support of Parcelize on all Darwin (Apple) targets! Which means it's now possible to preserve the state not only on Android. Please read the updated readme.

    This change shouldn't affect your project's runtime. If you have any problems or questions, please file an issue or a discussion.

    Versions and dependencies

    Kotlin: 1.7.21 parcelize-darwin: 0.1.2

    Source code(tar.gz)
    Source code(zip)
  • 0.6.0(Aug 20, 2022)

  • 0.5.2(Aug 4, 2022)

    • Added initialState argument to LifecycleRegistry builder function (#61, #65)
    • Added back-handler module, deprecated back-pressed module (#62)

    The new BackHandler

    This release introduces a new API for back button handling - BackHandler (back-handler module). The back-pressed module is entirely deprecated and will be removed in the next release. See the updated readme and refer to #57 for more information.

    Versions and dependencies

    Kotlin: 1.7.10

    Source code(tar.gz)
    Source code(zip)
  • 0.4.2(Jul 13, 2022)

  • 0.4.1(Jul 1, 2022)

  • 0.4.0(Jun 22, 2022)

  • 0.3.0(May 1, 2022)

  • 0.2.2(Oct 12, 2021)

  • 0.2.1(Oct 4, 2021)

  • 0.2.0(Oct 3, 2021)

    • Fixed potential memory leaks in LifecycleRegistry (#24)
    • LifecycleRegistry.unsubscribe method no longer throws an exception when called without being subscribed (#24)
    • Added InstanceKeeper.remove method (#25)
    • Bumped compileSdkVersion and targetSdkVersion to 31 (#29)
    Source code(tar.gz)
    Source code(zip)
  • 0.1.4(Sep 11, 2021)

  • 0.1.3(Aug 11, 2021)

    • Updated Kotlin to 1.5.21 (#19)
    • Added BackPressedHandler(OnBackPressedDispatcher) Android interop functions, deprecated BackPressedDispatcher(OnBackPressedDispatcher) Android interop functions (#18)
    • Added BackPressedHandlerOwner interface (#17)
    Source code(tar.gz)
    Source code(zip)
  • 0.1.2(Aug 4, 2021)

  • 0.1.1(Jul 20, 2021)

  • 0.1.0(Jul 18, 2021)

Owner
Arkadii Ivanov
Android developer. Passionate about Kotlin Multiplatform, MVI and reactive programming.
Arkadii Ivanov
Trikot / kotlin multiplatform libraries

Trikot / kotlin multiplatform libraries Table of contents Introduction Modules Samples License Introduction Trikot is a framework that helps building

Mirego 56 Dec 15, 2022
🧸 A multiplatform coroutine-based wrapper for popular platform-specific Redis client libraries

?? rekt ⚠️ WARNING! This project is experimental and may be missing essential features. Please let us know if you found any issues or have any suggest

Hexalite Network 3 Aug 31, 2022
🧸 A multiplatform coroutine-based wrapper for popular platform-specific Redis client libraries

?? rekt ⚠️ WARNING! This project is experimental and may be missing essential features. Please let us know if you found any issues or have any suggest

Southdust Team 3 Aug 31, 2022
The most complete and powerful data-binding library and persistence infra for Kotlin 1.3, Android & Splitties Views DSL, JavaFX & TornadoFX, JSON, JDBC & SQLite, SharedPreferences.

Lychee (ex. reactive-properties) Lychee is a library to rule all the data. ToC Approach to declaring data Properties Other data-binding libraries Prop

Mike 112 Dec 9, 2022
Most used extension methods for Kotlin

Extensify Most used extension methods for Kotlin Download Step 1. Add the JitPack repository to your build file allprojects { repositories {

Mobven 36 Aug 25, 2022
Ethereum Web3 implementation for mobile (android & ios) Kotlin Multiplatform development

Mobile Kotlin web3 This is a Kotlin MultiPlatform library that ... Table of Contents Features Requirements Installation Usage Samples Set Up Locally C

IceRock Development 32 Aug 26, 2022
Kotlin Multiplatform is an SDK for cross-platform mobile development, which enables teams to use the same business logic in both Android and iOS client applications.

Kotlin Multiplatform is an SDK for cross-platform mobile development, which enables teams to use the same business logic in both Android and iOS client applications.

Chris Russell 1 Feb 11, 2022
A Lightweight PDF Viewer Android library which only occupies around 125kb while most of the Pdf viewer occupies up to 16MB space.

Pdf Viewer For Android A Simple PDF Viewer library which only occupies around 125kb while most of the Pdf viewer occupies upto 16MB space. How to inte

Rajat 362 Dec 29, 2022
This lib implements the most common CoroutineScopes used in Android apps.

AndroidCoroutineScopes Starting from 0.26.0 release we should define a scope for new coroutines (docs). To avoid this boilerplate code I've created th

Adriel Café 15 Oct 3, 2022
An android lib that provides most commonly used utility function

Awesome-Utility An android lib that provides most commonly used utility function. It can help Android developers with supporting common utility functi

Ameer Hamza 2 Apr 5, 2022
Run Kotlin/JS libraries in Kotlin/JVM and Kotlin/Native programs

Zipline This library streamlines using Kotlin/JS libraries from Kotlin/JVM and Kotlin/Native programs. It makes it possible to do continuous deploymen

Cash App 1.5k Dec 30, 2022
🔨 Template for easy hosting of your Java/Kotlin libraries on GitHub

?? kotlin-jvm-library-template Another template for easy hosting your Java/Kotlin libraries on GitHub. Features boilerplate for Kotlin/Java projects w

Viktor 0 Jan 7, 2022
Android project setup files when developing apps from scratch. The codebase uses lates jetpack libraries and MVVM repository architecture for setting up high performance apps

Android architecture app Includes the following Android Respository architecture MVVM Jepack libraries Carousel view Kotlin Kotlin Flow and Livedata P

null 2 Mar 31, 2022
An awesome list that curates the best KMM libraries, tools and more.

Awesome KMM Kotlin Multiplatform Mobile (KMM) is an SDK designed to simplify creating cross-platform mobile applications. With the help of KMM, you ca

Konstantin 994 Dec 28, 2022
Automatically empty the trash in all of your Plex libraries

Plex Auto Trash Automatically empty the trash in all of your Plex libraries. If you disable automatic trash emptying (and you probably should) trash s

Jake Wharton 25 Aug 11, 2022
Account-lib - A suite of libraries to facilitate the usage of account-sdk

Usage Clone this repository (skip this step if the repo is on your local machine). The default branch is fine. git clone https://github.com/AFBlockcha

null 0 May 24, 2022
A personal project made using Jetpack Compose, Clean-MVVM architecture and other jetpack libraries

A basic CRUD for recording your personal credit and debit transactions. Made using Jetpack Compose, Clean-MVVM and other Jetpack libraries, incorporated with Unit Tests.

Shoaib Ahmed 3 Dec 6, 2022
The AppMetrica Push SDK is a set of libraries for working with push notifications.

Flutter AppMetrica Push AppMetrica Push SDK — это набор библиотек для работы с push-уведомлениями. Подключив AppMetrica Push SDK, вы можете создать и

Mad Brains 6 Oct 12, 2022
Boilerplate code for implementing MVVM in Android using Jetpack libraries, coroutines, dependency injection and local persistance

MVVM Foundation This projects aims to speed up development of Android apps by providing a solid base to extend Libraries Jetpack Fragment Material3 :

Gabriel Gonzalez 2 Nov 10, 2022