๐ A simple way to implement applications using observable streams
โโโ โโโ โโโโโโโ โโโโโโโโโโโโ โโโโโโโ โโโ โโโโ โโโโ โโโโโโ โโโโโโโโโโโโโโโโ
โโโ โโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโ โโโ โโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโ โโโ โโโ โโโ โโโ โโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโ โโโโโโ
โโโโโโโ โโโ โโโ โโโ โโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโ โโโโโโ
โโโ โโโโโโโโโโโโ โโโ โโโโโโโโโโโโโโ โโโโโโ โโโ โโโ โโโโโโ โโโโโโโโโโโโโโโโโโโ
โโโ โโโ โโโโโโโ โโโ โโโโโโโโโโโโโโ โโโโโ โโโ โโโโโโ โโโโโโโโโโโโโโโโโโโ
Usage
Create immutable view model
Recommend create class as comparable like
data
class
data class HelloModel(
val name: String = ""
)
MazeListener
Implement class HelloFragment : BaseFragment(), MazeListener<HelloModel> {
override val layoutId: Int = R.layout.fragment_hello
// Don't be in lifecycle of `Fragment`/`Activity`
// In this case, `BaseFragment` is set to `retainInstance = true` basically
// Set initial view model
private val maze by lazy { Maze(HelloModel()) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// Attach maze with user events
// Event.id is used to filter in `main` function
maze.attach(this, arrayOf(
toolbar.navigationClicks()
.map { ClickEvent(R.id.homeAsUp) },
inputName.textChanges()
.map { TextChangeEvent(R.id.inputName, it) }
))
}
override fun onDestroyView() {
// Detach
maze.detach()
super.onDestroyView()
}
// Implement main function
override fun main(sources: Sources<HelloModel>) = helloMain(sources)
// Render view model
override fun render(prev: HelloModel, curr: HelloModel) {
val hello = getString(R.string.hello_message)
textHello.text = hello.format(curr.name)
}
// Navigate somethings
override fun navigate(navigation: Navigation) {
when (navigation) {
is Back -> activity?.onBackPressed()
}
}
// Cleanup if Activity is finished
override fun finish() = maze.finish()
// Handle errors
override fun error(t: Throwable) {
t.printStackTrace()
}
}
Implement main function
Implement main logic using Observable
s
fun helloMain(sources: Sources<HelloModel>): Sinks<HelloModel> {
val model = sources.event
.textChanges(R.id.inputName)
.map(CharSequence::toString)
.withLatestFrom(sources.model,
BiFunction { name: String, model: HelloModel ->
model.copy(name = name)
})
.cacheWithInitialCapacity(1)
val navigation = sources.event
.clicks(R.id.homeAsUp)
.map { Back() }
// `model` must be `ObservableCache`
return Sinks(model, navigation)
}
Navigation
s, Event
s
Customize You can extend Navigation
s and/or Event
s if you want
Please refer to default
Navigation
s,
Event
s
More examples
Install
repositories {
jcenter()
}
compile "com.importre:kotlin-maze:$maze_version"
for test
testCompile "com.importre:kotlin-maze-test:$maze_version"
Slides
License
Apache 2.0 ยฉ Jaewe Heo