knot3d for android,GitHub - beworker/knot: Unidirectional reactive state container for Android & Kot...

68747470733a2f2f696d672e736869656c64732e696f2f62616467652f70726f64756374696f6e2d72656164792d627269676874677265656e2e737667

68747470733a2f2f7472617669732d63692e6f72672f6265776f726b65722f6b6e6f742e7376673f6272616e63683d6d6173746572

68747470733a2f2f636f6465636f762e696f2f67682f6265776f726b65722f6b6e6f742f6272616e63682f6d61737465722f67726170682f62616467652e737667

68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d417061636865253230322e302d626c75652e737667

🧶 Knot

Concise reactive state container library for Android applications.

Concept

Knot helps managing application state by reacting on events and performing asynchronous actions in a structured way. There are five core concepts Knot defines: State, Change, Action, Reducer and Effect.

5bb4091a118d70002f0dddeaacf31e36.png

State represents an immutable state of an application. It can be a state of a screen or a state of an internal statefull headless component.

Change is an immutable data object with an optional payload intended for changing the State. A Change can be produced from an external source or be a result of execution of an Action.

Action is a synchronous or an asynchronous operation which, when completed, can – but doesn't have to – emit a new Change.

Reducer is a function that takes the previous State and a Change as arguments and returns the new State and an optional Action wrapped by the Effect class. Reducer in Knot is designed to stay side-effects free because each side-effect can be turned into an Action and returned from the reducer function together with a new state in a pure way.

Effect is a convenient wrapper class containing the new State and an optional Action. If Action is present, Knot will perform it and provide resulting Change (if any) back to the Reducer.

In addition to that each Knot can subscribe to Events coming from external sources and turn them into Changes for further processing.

Getting Started

The example below declares a Knot capable of loading data, handling Success and Failure loading results and reloading data automatically when an external "data changed" signal gets received. It also logs all State mutations as well as all processed Changes and Actions in console.

sealed class State {

object Initial : State()

object Loading : State()

data class Content(val data: String) : State()

data class Failed(val error: Throwable) : State()

}

sealed class Change {

object Load : Change() {

data class Success(val data: String) : Change()

data class Failure(val error: Throwable) : Change()

}

}

sealed class Action {

object Load : Action()

}

val knot = knot {

state {

initial = State.Initial

}

changes {

reduce { change ->

when (change) {

is Change.Load -> State.Loading + Action.Load

is Change.Load.Success -> State.Content(data).only

is Change.Load.Failure -> State.Failed(error).only

}

}

}

actions {

perform {

switchMapSingle {

loadData()

.map { Change.Load.Success(it) }

.onErrorReturn { Change.Load.Failure(it) }

}

}

}

events {

source {

dataChangeObserver.signal.map { Change.Load }

}

}

}

val states = knot.state.test()

knot.change.accept(Change.Load)

states.assertValues(

State.Initial,

State.Loading,

State.Content("data")

)

Notice how inside the reduce function a new State can be combined with an Action using + operator. If only the State value should be returned from the reducer, the .only suffix is added to the State.

Composition

If your knot becomes complex and you want to improve its readability and maintainability, you may consider to write a composite knot. You start composition by grouping related functionality into, in a certain sense, indecomposable pieces called Delegates.

8bbfb918ae23e2a55b7382f1cdaac6a6.png

Each Delegate is isolated from the other Delegates. It defines its own set of Changes, Actions and Reducers. It's only the State, what is shared between the Delegates. In that respect each Delegate can be seen as a separate Knot working on a shared State. Once all Delegates are defined, they can be composed together and provided to CompositeKnot which implements standard Knot interface. For more information check out Composite ViewModel post.

Documentation

Knot Sample App is the first place to look at.

Async Actions to learn how to perform and cancel asynchronous actions.

External Events to learn how to observe and handle external events.

Composite ViewModel to learn more about composition.

Other examples

Why Knot?

Predictable - state is the single source of truth.

Side-effect free reducer - by design.

Scalable - single knots can be combined together to build more complex application logic.

Composable - complex knots can be composed out of delegates grouped by related functionality.

Structured - easy to read and write DSL for writing better structured and less buggy code.

Concise - it has minimalistic API and compact implementation.

Testable - reducers and transformers are easy to test.

Production ready - Knot is used in production.

Why not?

RxJava3 Binaries 687474703a2f2f696d672e736869656c64732e696f2f6d6176656e2d63656e7472616c2f762f64652e68616c666269742f6b6e6f74332e737667

allprojects {

repositories {

mavenCentral()

}

}

dependencies {

implementation "de.halfbit:knot3:"

// Becase Knot is not released for each and every RxJava version,

// it is recommended you also explicitly depend on RxJava's latest

// version for bug fixes and new features.

implementation 'io.reactivex.rxjava3:rxjava:3.0.4'

}

RxJava2 Binaries 687474703a2f2f696d672e736869656c64732e696f2f6d6176656e2d63656e7472616c2f762f64652e68616c666269742f6b6e6f742e737667

allprojects {

repositories {

mavenCentral()

}

}

dependencies {

implementation "de.halfbit:knot:"

// Becase Knot is not released for each and every RxJava version,

// it is recommended you also explicitly depend on RxJava's latest

// version for bug fixes and new features.

implementation 'io.reactivex.rxjava2:rxjava:2.2.19'

}

Inspiration

Knot was inspired by two awesome projects

License

Copyright 2019, 2020 Sergej Shafarenka, www.halfbit.de

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值