https://kotlinlang.org logo
#android-architecture
Title
# android-architecture
a

Ahmed Ibrahim

03/20/2020, 10:53 AM
I'm wondering in the Clean Architecture onion diagram. In which layer should the navigation and tracking be in? For the navigation it seems better to belong to the presentation layer, however it could also be part of the use case layer. As it could be part of a use case description "When a user clicks on a product, if the product is a collection then head to the collections screen, otherwise head to the product details screen" I'm curious what do experts think 🤔
f

Francisco Javier Ruiz Rodriguez

03/20/2020, 11:02 AM
The decision is done on the use case layer, but this layer knows nothing about how it is implemented, so the navigation layer (in my opinion) may be in the last layer
s

streetsofboston

03/20/2020, 11:25 AM
Like Francisco said, the UseCase layer is some action/use-case that was finished with a particular result. Then a navigation/navigator in the Presenter (ViewModel) determines which screen to go to. It instructs the Framework to handle all the specific details of how to get to that screen (eg JetPack Navigation, plain Fragment, going to another Activity, etc)
a

Ahmed Ibrahim

03/20/2020, 11:29 AM
But from what I understood from Francisco, is that the navigator will be the injected in the use case, and the implemenation will be provided from the top most layer through inversion of control, right @Francisco Javier Ruiz Rodriguez? While you're suggestion is that use case layer doesn't know anything about the navigator and the presentation layer will check the result of the usecase to handle the navigation.
So they're two different approaches.
f

Francisco Javier Ruiz Rodriguez

03/20/2020, 11:32 AM
Nope exactly, @Ahmed Ibrahim. I'm with Anton, the use case must response the presenter what to do, but whithout any knowledge of how it is done
i

Ianmedeiros

03/20/2020, 12:15 PM
It’s all on paper, but I think that if you are going to use AAC, you are FORCED to do navigation on the UI layer -> you can’t inject fragments/activities into the view-model even as interfaces.
And they are the only framework components that know how to navigate. It doesn’t matter if you use the new navigation component or old-style fragment transaction.
a

Ahmed Ibrahim

03/20/2020, 12:20 PM
@Ianmedeiros I think you can get around that by using the inversion of control principle, there are solutions already for that problem, one of them is using the same approach as Cicerone using https://github.com/terrakok/Cicerone By buffering navigation commands and once the activity is ready, execute them one by one.
i

Ianmedeiros

03/20/2020, 12:20 PM
So, you will need to observe navigation events from the activity/fragment and they are the ones that actually navigate. You can abstract out this concept, but I couldn’t find a good abstraction that would make the code easyer to understand..
There are some problems with this implementation when you start to implement multi-module
I know that you can invert the control, but after going back and forth with different abstractions trying to invert the controll to the presenter (ViewModel), I got to the conclusion that simple emmiting the event to the fragment / activity was easier to understand. Specially when you are injecting different destinations.
👍 2
a

Ahmed Ibrahim

03/20/2020, 12:26 PM
For me I found out emitting a UIEvent (which is a one-off event like Showing snack bars or toast), is the most suitable solution for me, in terms of easy to implement and understand.
i

Ianmedeiros

03/20/2020, 12:26 PM
I agree.
But who actually navigates is the fragment in my case. He is observing those UiEvents and some of them are handled as navigation events.
The ViewModel doesn’t even know that the UI will navigate in my case
I really tried to introduce this “Router” concept in my view-models, but IMO, it did not made the code easier to understand and extend.
And I am not very fond of this Cicerone implementation: having to always call it onResume + onPause, than injecting it with dagger in the view-model + injecting custom destinations, etc. It seems harder than simple emmiting an event “OnForwardCommandClick” from the view model and simple using a fragmentStack operation?
a

Ahmed Ibrahim

03/20/2020, 12:41 PM
But in case of Single Activity application, you'll have it only in one place, no?
i

Ianmedeiros

03/20/2020, 12:47 PM
You will have only one Navigator for the app?
Doesn’t you need to install a
Navigator
on every onResume?
I imagine that you need to inject different
Navigators
for different features…
So, now you will need to introduce probably a new abstraction?
s

Steve

03/20/2020, 4:18 PM
Putting navigation in the Use Case layer would make it really difficult to test, I would think
c

corneil

03/23/2020, 8:53 AM
Use Case layer is responsible for changing or representing state. The layers out from there may know how to act on a specific state. The representation and navigation is in the UI. So the UI must know how to best represent the state in some cases you want to let the UI know which events are allowed for current state because it is tied to a specific state model. Then that information becomes part of the representation of the state and the UI doesn't have to replicate the decision. I use this when I do a finite state machine. I allow for the FSM to provide a list of events that should be possible. The UI doesn't have to figure it out. Show/Hide or Enable/Disable events as best fit the UX.
💯 1
f

Fatih

04/30/2020, 4:14 PM
Lots of different opinions. @Ahmed Ibrahim use whatever works best for you and as long as it is unit testable
7 Views