Comments (14)
This is because I want all changes to be reasonable.
from mvikotlin.
This sounds like a good idea! Would you like to submit a PR?
from mvikotlin.
You want a PR for just adding the keyword "fun" in front of the interface?
from mvikotlin.
Well yes. I can do it by myself probably later this week.
from mvikotlin.
While you're at it ViewRenderer should also be a fun interface
from mvikotlin.
I would keep ViewRenderer
as it is unless there is a use case.
from mvikotlin.
What is the use case for NOT making ViewRenderer
a fun interface. Basically any interface with a single abstract non-suspend method should probably be a fun interface unless there is a compelling reason not to
The use case is that I am not using MviView mostly because I don't want to use ViewEvents on Android since I am using FlowBinding library to create a Flow directly without all the boiler plate. So I deal with a ViewRender directly, but even if using BaseMviView it has a field where you can set a ViewRenderer.
If I don't use diffing I have to do something like this to create a ViewRenderer:
val renderer = object: ViewRenderer<State> {
override fun render(model: State) {
label.text = model.value
}
}
Adding fun to ViewRenderer lets you simplify to
val renderer = ViewRenderer<State> { label.text = it.value }
Your reaction implies to me that you may not fully understand the benefits of a fun interface. There is a great article on the subject.
from mvikotlin.
I think in your case you can just use normal functions, so your renderer becomes just a consumer of ViewModels: (Model) -> Unit
.
Regarding BaseMviView
: you can just override its render
method, no need to assign the renderer
property.
The ViewRenderer
interface is not meant to be created anonymously, but if you think it makes sense then let's make it fun
interface as well.
from mvikotlin.
I think in your case you can just use normal functions, so your renderer becomes just a consumer of ViewModels: (Model) -> Unit.
Except that is not type compatible with diff function
Regarding BaseMviView: you can just override its render method, no need to assign the renderer property.
But you allow for it so someone could want to use the property
The ViewRenderer interface is not meant to be created anonymously, but if you think it makes sense then let's make it fun interface as well.
Which was my point because I do want to create it anonymously
from mvikotlin.
Could you kindly provide a code snippet? From my point of view, you either use diff
or normal Kotlin functions. In neither case you need to create ViewRenderer
anonymously.
from mvikotlin.
So in my case I have no MviView implementation class. The controller onViewCreated looks like this:
fun onViewCreated(
viewLifecycle: Lifecycle,
renderer: ViewRenderer<State>,
intents: Flow<Intent>,
eventHandler: suspend (Event) -> Unit
) {
bind(viewLifecycle, BinderLifecycleMode.CREATE_DESTROY) {
intents bindTo store
store.states bindTo renderer
store.labels bindTo eventHandler
}
}
In my Android fragment I have:
val intents = merge(
button1.clicks().map { SomeIntent },
button2.clicks().map { AnotherIntent },
...
)
val renderer = object: ViewRenderer<State> {
override fun render(model: State) {
label.text = model.data
}
}
And then to call the controller I have:
controller.onViewCreated(
viewLifecycleOwner.lifecycle.asMviLifecycle(), renderer, intents
) {
// handle labels here
}
So I could switch the controller parameter to just take (Model) -> Unit and change the renderer field to just be a lambda BUT if I decided later that the renderer did need to use diff I would also have to switch the controller to ViewRenderer. So it is best to stay with ViewRenderer so the Controller doesn't know the difference.
Making ViewRenderer a functional interface means I can use this to declare the renderer:
val renderer = ViewRenderer<State> { label.text = it.data }
and if I want to switch renderer to diff I can say:
val renderer = diff { diff(State::data) { label.text = it } }
without changing the Controller at all
from mvikotlin.
Thanks, that is a valid use case indeed. Will love to make ViewRenderer
a fun interface.
from mvikotlin.
That sure was a lot of discussion to get a total of 4 characters added to a file
from mvikotlin.
Looks like marking an interface as fun
may be a breaking change.
For example, the following case fails with StackOverflowError
after making ViewReneder
a fun interface:
override fun <Model : Any> Observable<Model>.bindTo(viewRenderer: ViewRenderer<Model>) {
this bindTo {
assertOnMainThread()
viewRenderer.render(it)
}
}
This function becomes recursive once ViewRenderer
is marked as fun
, because now this lambda is treated as ViewRenderer
due to SAM conversion.
I think I will keep ViewRenderer
as it is for now. You can add the following function to reduce the boilerplate:
inline fun <T : Any> viewRenderer(crossinline render: (T) -> Unit): ViewRenderer<T> =
object : ViewRenderer<T> {
override fun render(model: T) {
render.invoke(model)
}
}
from mvikotlin.
Related Issues (20)
- Add watchOS support HOT 2
- Deploy JS sample app to hosting as working example HOT 1
- Memory leak using "LifecycleExt.kt" HOT 7
- Unit Testing the CalculatorStoreFactory (from the website tutorial)... ???
- Rename SuspendExecutor to CoroutineExecutor and SuspendBootstrapper to CoroutineBootstrapper HOT 1
- Can't export time travel data HOT 3
- BypassReducer does nothing HOT 2
- Support new Apple silicon targets
- Try to allow Stores with same names when using time travel
- Suggestion to improve API for CoroutineExecutor HOT 2
- Add settings dialog to the time travel IDEA plugin HOT 1
- Describe the time travel feature in more detail HOT 2
- Add binary-compatibility-validator plugin to all published modules
- Consider better names for Action and Result HOT 3
- TimeTravelServer for web HOT 1
- Broken links in the time travel docs HOT 1
- Setup CI for publishing the time travel desktop app HOT 1
- Update KDocs in CoroutineExecutor HOT 5
- How to work around bootstrapper action publishing label before listener set up HOT 5
- Mvi
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mvikotlin.