Git Product home page Git Product logo

stateful's Introduction

Stateful

Annotation processor library that generates a stateful wrapper and an Update listener interface for model classes.

Example

You have a simple Model and a View that renders the model.

data class Model(
    val title: String,
    val titleFontSize: Float?,
    val isTitleVisible: Boolean
)

class View {
    fun render(model: Model) {
        /* renders the model */
    }
}

Instead rendering everything on every update or checking the updates manually

  • Annotate the Model
@Stateful
data class Model( ... )
  • Build. For the above model, the processor will generate the following classes
interface ModelUpdateListener {
    fun onTitleUpdated(newTitle: String) {}
    fun onTitleUpdated(oldTitle: String?, newTitle: String) {}
    fun onTitleUpdated(newModel: Model) {}
    fun onTitleUpdated(oldModel: Model?, newModel: Model) {}

    fun onTitleFontSizeUpdated(newTitleFontSize: Float?) {}
    fun onTitleFontSizeUpdated(oldTitleFontSize: Float?, newTitleFontSize: Float?) {}
    fun onTitleFontSizeUpdated(newModel: Model) {}
    fun onTitleFontSizeUpdated(oldModel: Model?, newModel: Model) {}

    fun onIsTitleVisibleUpdated(newIsTitleVisible: Boolean) {}
    fun onIsTitleVisibleUpdated(oldIsTitleVisible: Boolean?, newIsTitleVisible: Boolean) {}
    fun onIsTitleVisibleUpdated(newModel: Model) {}
    fun onIsTitleVisibleUpdated(oldModel: Model?, newModel: Model) {}
}

class StatefulModel(
    private val modelUpdateListener: ModelUpdateListener,
    initialModel: Model? = null
) {
    private var currentModel = initialModel

    fun accept(newModel: Model) {
        if (!Objects.equals(currentModel?.title, newModel.title)) {
            modelUpdateListener.onTitleUpdated(newModel.title)
            modelUpdateListener.onTitleUpdated(currentModel?.title, newModel.title)
            modelUpdateListener.onTitleUpdated(newModel)
            modelUpdateListener.onTitleUpdated(currentModel, newModel)
        }

        if (!Objects.equals(currentModel?.titleFontSize, newModel.titleFontSize)) {
            modelUpdateListener.onTitleFontSizeUpdated(newModel.titleFontSize)
            modelUpdateListener.onTitleFontSizeUpdated(currentModel?.titleFontSize, newModel.titleFontSize)
            modelUpdateListener.onTitleFontSizeUpdated(newModel)
            modelUpdateListener.onTitleFontSizeUpdated(currentModel, newModel)
        }

        if (!Objects.equals(currentModel?.isTitleVisible, newModel.isTitleVisible)) {
            modelUpdateListener.onIsTitleVisibleUpdated(newModel.isTitleVisible)
            modelUpdateListener.onIsTitleVisibleUpdated(currentModel?.isTitleVisible, newModel.isTitleVisible)
            modelUpdateListener.onIsTitleVisibleUpdated(newModel)
            modelUpdateListener.onIsTitleVisibleUpdated(currentModel, newModel)
        }

        currentModel = newModel
    }
}
  • Implement the above interface, overriding whatever makes sense and pass all model updates through the Stateful wrapper class.
class View : ModelUpdateListener {
    private val statefulModel = StatefulModel(this)

    fun render(model: Model) {
        statefulModel.accept(model)
    }

    override fun onTitleUpdated(newTitle: String) {
        /* update the title */
    }
}

Install

  • Configure your project to consume GitHub packages
    • Generate an access token with read packages permission, more details here: GitHub Help
    • Add the maven repository to your Project dependencies; username is your user ID and password is the key generated previously
allprojects {
    repositories {
        maven {
            url = uri("https://maven.pkg.github.com/iFanie/Stateful")
            credentials {
                username = ...
                password = ...
            }
        }
    }
}
  • Add kapt generated classes to your Module sourceSets
sourceSets {
    main {
        java {
            srcDir "${buildDir.absolutePath}/generated/source/kaptKotlin/"
        }
    }
}
  • Add the Stateful dependencies to your Module
dependencies {
    implementation 'dev.fanie:stateful:0.0.1'
    kapt 'dev.fanie:stateful-compiler:0.0.1'
}
  • You can use the app module as a reference for how the packages are accessed and used

stateful's People

Contributors

ifanie avatar

Watchers

 avatar

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.