-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes occurring independent of user interaction #7
Comments
Hey @glurt. You say that the change occurs as a result of something other than user interaction yet the UI is observing the result of that change? Then why not have an |
@jshvarts Even though it works, that approach leads to some tightly coupled design. UI needs to be aware of the source which can influence the data like network etc. A better design is for UI to just rely on the redux store as source of truth and not care about how the actions/events causes data change. Other user initiated UI actions, platform initiated events (broadcast, sensor, location update etc), backend server triggered events (domain logic, push notification etc) would just need to update the store. All consumers of the store (analytics, logging) including UI will just work out of the box. |
Can you point me to some other redux implementations on Android that do something similar? We have not had the need to do this but PRs are welcome |
Not a redux implementation per se but Room's LiveData update is an example. It doesn't matter how the data was updated in the database (network/UI or other background tasks), all registered observers (including UI if in resumed state) are notified of the new update via LiveData. It offers a better separation of concerns, makes testing easier and encourages a plug-in design. As it looks many implementations of UDF works well when UI is the only beneficiary/driver of the data store but not with consumers like services, work manager tasks etc. |
I've just finished refactoring one of the screens in my app which is using Room as a datasource, the ViewModel is setup to receive the initial Each of these Observables is mapped to a So in essence, we can treat external changes as I'm not sure if this is the best way of approaching this but it seems to work for my scenario, I'd imagine that if you needed to listen for broadcasts or notifications you could map them into |
So looks like we have a good solution here. Treat background/external changes as |
^ This seems to be the most logical approach. It lends itself to easy testing, and it keeps everything consistent. My only concern with this approach is that it could end up exposing some Actions to the Activity that should not be. //Inside MyActivity
dispatchAction(Action.UserInitiatedAction) //OK
dispatchAction(Action.ExternalAction) //Not all ExternalActions should be visible to Activity Depending on how you declare your Actions, perhaps some visibility modifier magic might mitigate this. |
It may not even be necessary to define the Actions for external changes. For UI it makes sense because the Activity/Fragment knows about the ViewModel and needs to send something to the ViewModel so that it knows what it needs to react to. UserInitiatedAction is a good way of representing that. External events are probably going to come from multiple places that don't know about the ViewModel, like repositories, callbacks etc. therefore they don't know about the Actions defined within. If the ViewModel implements a listener it can simply emit a Change using a Subject and have that Subject feed into the the reducer like so
|
Interesting idea @glurt. Will try it out |
@glurt, that's something similar to what we've done - except rather than an explicit fun bindActions() {
val load = actions.ofType<Action.Load>()
.switchMap {
useCase.load() // Our normal load stuff.
.map<Change> { Change.Load(it) }
.onErrorReturn { Change.LoadError(it) }
.mergeWith(useCase.triggerSomePublisherEmitterThing().map<Change> { Change.External }) // Our external change stuff.
.onErrorReturn { Change.ErrorWithPublisherEmitterThing(it) }
...
}
}
|
@glurt This is how we have implemented it right now: ViewModel adds a listener for the external change, and in response to the change it emits a |
Hey there, I've been reading the wiki to figure out if this library is right for me. I like the idea of mapping actions into changes and having the UI respond to state changes but I feel like the use case might be a bit narrow.
Quite often a change occurs as a result of something other than user interaction, as an example let's say my app is polling a server for live sports results, normally these changes would come through the backend of the app and update a property in the ViewModel/Presenter which the UI is observing.
Is it possible (or even necessary) to represent external events as actions and treat them the same as user interaction, especially if they aren't coming from the UI layer?
The text was updated successfully, but these errors were encountered: