Giter Club home page Giter Club logo

ensody / reactivestate-kotlin Goto Github PK

View Code? Open in Web Editor NEW
33.0 3.0 2.0 1.66 MB

Easy reactive state management and ViewModels for Kotlin Multiplatform. No boilerplate. Compatible with Android.

Home Page: https://ensody.github.io/ReactiveState-Kotlin/

License: Apache License 2.0

Kotlin 97.56% Dockerfile 0.13% Shell 1.65% Python 0.67%
android-library state-management kotlin-android reactive mobile-development mobx android lifecycle stateflow demand-driven

reactivestate-kotlin's Introduction

ReactiveState for Kotlin Multiplatform and Android

Maven Central

Easy reactive state management and ViewModels for Kotlin Multiplatform. No boilerplate. Compatible with Android.

ReactiveState-Kotlin provides these foundations for building multiplatform ViewModels and lower-level logic:

See the ReactiveState documentation for more details.

Supported platforms

android, jvm, ios, tvos, watchos, macosArm64, macosX64, mingwX64, linuxX64

Installation

Add the package to your build.gradle's dependencies {}:

dependencies {
    // Add the BOM using the desired ReactiveState version
    api platform("com.ensody.reactivestate:reactivestate-bom:VERSION")

    // Leave out the version number from now on:
    implementation "com.ensody.reactivestate:reactivestate"

    // Utils for unit tests that want to use coroutines
    implementation "com.ensody.reactivestate:reactivestate-test"
    // Note: kotlin-coroutines-test only supports the "jvm" target,
    // so reactivestate-test has the same limitation
}

Also, make sure you've integrated the Maven Central repo, e.g. in your root build.gradle:

subprojects {
    repositories {
        // ...
        mavenCentral()
        // ...
    }
}

Quick intro

The following two principles are here to give you a quick idea of the reactive programming aspect only. The "Guide" section in the documentation describes how to work with the more advanced aspects like multiplatform ViewModels, lifecycle handling, etc.

Note: While the discussion is about StateFlow, you can also use LiveData or even implement extensions for other observable values.

Observing StateFlow

Imagine you have an input form with first and last name and want to observe two StateFlow values at the same time:

  • isFirstNameValid: StateFlow<Boolean>
  • isLastNameValid: StateFlow<Boolean>

This is how you'd do it by using the autoRun function:

autoRun {
    submitButton.isEnabled = get(isFirstNameValid) && get(isLastNameValid)
}

With get(isFirstNameValid) you retrieve isFirstNameValid.value and at the same time tell autoRun to re-execute the block whenever the value is changed. That code is similar to writing this:

lifecycleScope.launchWhenStarted {
    isFirstNameValid
        .combine(isLastNameValid) { firstNameValid, lastNameValid ->
            firstNameValid to lastNameValid
        }
        .conflate()
        .collect { (firstNameValid, lastNameValid) ->
            try {
                submitButton.isEnabled = firstNameValid && lastNameValid
            } catch (e: CancellationException) {
                throw e
            } catch (e: Throwable) {
                onError(e)
            }
        }
}

Reactive StateFlow / reactive data

The same principle can be used to create a derived, reactive StateFlow:

val isFormValid: StateFlow<Boolean> = derived {
    get(isFirstNameValid) && get(isLastNameValid)
}

Now you can use autoRun { submitButton.isEnabled = get(isFormValid) } in the rest of your code.

Going even further, isFirstNameValid itself would usually also be the result of a derived computation. So, you can have multiple layers of reactive derived StateFlows.

Relation to Jetpack Compose / Flutter / React

Reactive UI frameworks like Jetpack Compose automatically rebuild the UI whenever e.g. a StateFlow changes. So, in the UI layer autoRun can usually be replaced with a Composable.

However, below the UI your data still needs to be reactive, too. Here ReactiveState provides derived to automatically recompute a StateFlow based on other StateFlows. This pattern is very useful in practice and provides the perfect foundation for frameworks like Jetpack Compose which primarily focus on the UI aspect. ReactiveState's derived and autoRun provide the same reactivity for your data and business logic.

In Jetpack Compose you even have derivedStateOf which is very similar to derived. So, you can choose whether you want to build your business logic based on the official coroutines library (StateFlow/derived) or Jetpack Compose (State/derivedStateOf). However, the coroutines library has the advantage that it's available for more platforms and it's fully independent of any UI frameworks. Finally, most open-source non-UI libraries will probably be based on coroutines, so StateFlow based code might also be better for compatibility/interoperability.

In other words, the combination of both solutions used together results in a fully reactive, multiplatform codebase - which improves code simplicity and avoids many bugs.

Moreover, Jetpack Compose currently doesn't provide any multiplatform ViewModel support or any large-scale architecture. So, this library solves that by providing BaseReactiveState for ViewModels. It also comes with a lifecycle-aware event system (eventNotifier) and loading state handling (so you can track one or multiple different loading indicators based on coroutines that you launch).

See also

This library is based on reactive_state for Flutter and adapted to Kotlin Multiplatform and Android patterns.

License

Copyright 2024 Ensody GmbH, Waldemar Kornewald

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.