Android Clean Architecture UseCase - android

I am developing a simple application.
The user navigates through the elements of the RecyclerView to the end screen.
When scrolling LastFragment to the very bottom of the fragment, the SharedPref saves the status to true. Then the next element becomes available.
LastFragment has a button that plays a sound when clicked
I'm trying to build an application according to the principles of clean architecture and
I don't understand where UseCase is. Could you explain to me which UseCase should be used here?

You need to have something like:
PersistEndWasReachedUseCase
Or whatever name you like that will call the: "SaveToSharePrefs" Logic.
They should be part of your Domain Layer:
https://developer.android.com/topic/architecture/domain-layer
But at the same time, you need to be clean. This means that your logic should not know where it saves states. It might be a DB, SharePrefs, a remote server, etc.
That is why you should you a repository pattern:
https://developer.android.com/codelabs/basic-android-kotlin-training-repository-pattern#0
https://www.raywenderlich.com/24509368-repository-pattern-with-jetpack-compose
So you need to also have a Data Layer:
https://developer.android.com/topic/architecture/data-layer
But long story short - what clean means - You put your business logic in the inner layers. They depend on interfaces declared in these layers. And then outside layers implement these interfaces.
Basically this is an Inversion of control. Check SOLID.
https://miro.medium.com/max/1400/1*B4LEEv0PbmqvYolUH-mCzw.png
As per the image - you push the implementation details: Room, SharedPrefs, etc in the outer layers. And the inner layers are pure Kotlin/Java code. It knows nothing about implementation details - they are hidden by interfaces.

Related

How to Implement MVI in Android using just Java

Please does anyone have a link to a resource that helps in learning how to create an app using mvi design pattern but all code should be in Java and not Kotlin
Before you click! This is in Kotlin -> https://tech.olx.com/mvi-architecture-in-android-a-simple-livedata-based-approach-b4b23896fd32 But if you actually look at the code snippets there is not a single line that doesn't have an obvious Java counter part. There is not a single Kotlin exclusive item like Flow, Scoping, Coroutine anywhere.
You don't need to learn Kotlin to understand it, just read it.
The article explains MVI as a modified way to use a MVVM.
It has 2 (ViewState/ViewEffect) components that are observed by the view (Fragment/Activity)
It has 1 (ViewEvent) component that is used by the view to trigger changes in the observed components above.
ViewState : It contains your data, like a List, like a boolean that determines if something is enabled, etc...
When there is a change in any state data, like an update to the List, the observer receives everything, and updates everything.
ViewEffect : These are one off "effects" like starting an animation, making a toast. You will update this with new data when you not concerned about the state of the effect. Like I don't care if there is another toast on the screen, atm. Just make a new one with new information, and show it.
ViewEvent : This allows the ViewModel to receive events from the view and start the "update" process. If a button is clicked in the view all the view would do is send a ViewEvent to the ViewModel stating what has been clicked. Then the ViewModel updates the ViewState/ViewEffect based on the ViewEvent received, which then propagates to the view.

UseCase with multiple response lists in Clean Architecture

I am using the Clean Architecture principle for my Android app.
I have a dashboard screen with two lists, one list with feeds, the other with events.
For this screen, I have a ViewModel that will contain the lists.
To provide the data to the ViewModel, I have a UseCase called ViewDashboardUseCase.
The UseCase makes use of two repositories, one for the feed entity and the other for the event entity.
Taking this information into account I have a few questions:
Is this the right approach to use the UseCase? Should I create two UseCases?
If I should use one UseCase, what is the best way to return the two lists from that UseCase and use them in the ViewModel.
At the 2017 Google Developer Days, Florina commented about separating your screen into what she called "logical units" and then observing these logical units on separate LiveData.
Basically, you would create two view states (or I believe, use cases, in your code) and then fill each view state with the list. Finally, expose these view state to your view using two LiveData.
Here's a video of the conference: https://www.youtube.com/watch?v=Ts-uxYiBEQ8
She starts talking about these around the 8 minute mark.
Should I create two UseCases?
Yes, you should use a UseCase per one Repository.
Depending on whether you need the lists to be "fed separately" (one at a time) or "combined" (simultaneously), the ViewModel might use either the two UseCases or a new UseCase combined of the two.

Is it ok for view to ask for data from ViewModel in MVVM?

I have been reading about MVVM pattern. View is supposed to observe for changes in ViewModel and act on it accordingly but I am confused if following code in View is ok in MVVM architecture.
fun onClick(view:View){
showUser(viewModel.getUserDisplayName())
}
Here View is not observing for a change, its rather asking for latest data from ViewModel. Is this considered correct in MVVM?
This is a question that possibly has no one answer, as different points might be made depending on the exact use case. However:
Sir Codesalot (great handle) is in my opinion technically correct. Let me elaborate.
In MVVM the view should pass UI interaction events (commands) to the ViewModel.
Here is an article from microsoft (who invented mvvm): https://msdn.microsoft.com/en-us/library/ff798384.aspx
The examples here are not related to android, but the concepts should be the same, especially if you look at the first diagram.
The ViewModel should do its magic, react to these events by manipulating data accordingly and then notify the observers (usually the view) of state changes. The view then reacts to the state changes.
In this way, if you would just pass data back from the ViewModel (in a synchronous way), then your view might be missing side effects. In your particular example, there probably aren't any, but consider that the method you call does not only return data, but also changes some internal state (e.g. counts the number of times the data was accessed). Then your view will not know of these.
Of course, you can make the case, that you can return all relevant data for the view, but it starts to break the single responsibility principle.
Here is an interesting blog post, which might give a better example, why the view should always get the state after the ViewModel: https://medium.com/upday-devs/mvvm-rxjava-learnings-1819423f9592
To the point of the other case, the wikipedia article about MVVM https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel states, that the ViewModel can expose public properties.
So in the end, it will most probably be cleaner if you do not return data directly. However, you are the architect and you know your app the best and there might be cases where patterns can be broken. After all they are guidelines. If you know why you break it (and maybe document it), then everything should work out.

How to handle UI based Navigation in Cross Platform Apps?

Assume that you have a cross platform application. The application runs on Android and on iOS. Your shared language across both platforms is Java. Typically you would write your business logic in Java and all you UI specific part in Java (for Android) and Objective-C (for iOS).
Typically when you implement the MVP pattern in a cross platform, cross language application you would have the Model and the Presenter in Java and provide a Java interface for your Views which is known to your presenters. This way your shared Java presenters can communicate with whatever view implementation you use on the platform specific part.
Lets assume we want to write a iOS app with a Java part which could be shared later on with the same Android app. Here is a graphical representation of the design:
On the left side there is the Java part. In Java you write your models, controllers as well as your view interfaces. You make all the wiring using dependency injection. Then the Java code can be translated to Objective-C using J2objc.
On the right side you have the Objective-C part. Here your UIViewController's can implement the Java interfaces which where translated into ObjectiveC protocols.
Problem:
What I am struggling about is how navigation between views takes place. Assume you are on UIViewControllerA and you tap a button which should bring you to UIViewControllerB. What would you do?
Case 1:
You report the button tap to the Java ControllerA (1) of UIViewControllerA and the Java ControllerA calls Java ControllerB (2) which is linked to UIViewControllerB (3). Then you have the problem that you do not know from the Java Controller side how to insert the UIViewControllerB in the Objective-C View hierarchy. You cannot handle that from the Java side because you have only access to the View interfaces.
Case 2:
You can make the transition to UIViewControllerB whether it is modal or with a UINavigationController or whatever (1). Then, first you need the correct instance of UIViewControllerB which is bind to the Java ControllerB (2). Otherwise the UIViewControllerB could not interact which the Java ControllerB (2,3). When you have the correct instance you need to tell Java ControllerB that the View (UIViewControllerB) has been revealed.
I am still struggling with this problem of how to handle the navigation between different controllers.
How can I model the navigation between different Controllers and handle the cross platform View changes appropriately?
Short answer:
Here is how we do it:
For simple "normal" stuff (like a button that opens the device camera or opens another Activity/UIViewController without any logic behind the action) - ActivityA directly opens ActivityB. ActivityB is now responsible communicating with the app shared logic layer if needed.
For anything more complex or logic dependent we're using 2 options:
ActivityA calls a method of some UseCase which returns an enum or public static final int and takes some action accordingly -OR-
Said UseCase can call a method of a ScreenHandler we registered earlier which knows how to open common Activities from anywhere in the app with some supplied parameters.
Long answer:
I'm the lead developer in a company using a java library for the application's models, logic, and business rules which both mobile platforms (Android and iOS) implement using j2objc.
My design principles come directly from Uncle Bob and SOLID, I really dislike the usage of MVP or MVC when designing whole applications complete with inter-component communications because then you start linking each Activity with 1 and only 1 Controller which sometimes is OK but most of the times you end up with a God Object of a controller that tends to change as much as a View. This can lead to serious code smells.
My favorite way (and the one I find cleanest) of handling this is breaking everything up into UseCases each of which handles 1 "situation" in the app. Sure you can have a Controller that handles several of those UseCases but then all it knows is how to delegate to those UseCases and nothing more.
Additionally, I don't see a reason of linking every action of an Activity to a Controller sitting in the logical layer, if this action is a simple "take me to the map screen" or anything of this sort. The role of the Activity should be handling the Views it holds, and as the only "smart" thing living in the life cycle of the application, I see no reason it can't call the start of the next activity itself.
Furthermore, Activity/UIViewController lifecycle is too complex and too different from each other to be handled by the common java lib. It is something I view as a "detail" and not really "business rules", each platform needs to implement and worry about, thus making the code in the java lib more solid and not prone to change.
Again, my goal is to have each component of the app be as SRP (Single Responsibility Principle) as it can be, and this means linking as few things together as possible.
So an example of simple "normal" stuff:
(all examples are totally imaginary)
ActivityAllUsers displays a list of model object items. Those items came from calling AllUsersInteractor - a UseCase controllerin a back thread (which in turn also handled by the java lib with a dispatch to main thread when the request is completed). The user clicks on one of the items in this list. In this example the ActivityAllUsers already has the model object so opening ActivityUserDetail is a straightforward call with a bundle (or another mechanism) of this data model object. The new activity, ActivityUserDetail, is responsible of creating and using the correct UseCases if further actions are needed.
Example of complex logic call:
ActivityUserDetail has a button titled "Add as a friend" which when clicked calls the callback method onAddFriendClicked in the ActivityUserDetail:
public void onAddFriendClicked() {
AddUserFriendInteractor addUserFriend = new AddUserFriendInteractor();
int result = addUserFriend.add(this.user);
switch(result){
case AddUserFriendInteractor.ADDED:
start some animation or whatever
break;
case AddUserFriendInteractor.REMOVED:
start some animation2 or whatever
break;
case AddUserFriendInteractor.ERROR:
show a toast to the user
break;
case AddUserFriendInteractor.LOGIN_REQUIRED:
start the log in screen with callback to here again
break;
}
}
Example of even more complex call
A BroadcastReceiver on Android or AppDelegate on iOS receive a push notification. This is sent to NotificationHandler which is in the java lib logical layer. In the NotificationHandler constructor which is constructed once in the App.onCreate() it takes a ScreenHandler interface which you implemented in both platforms. This push notification is parsed and the correct method is called in the ScreenHandler to open the correct Activity.
The bottom line is: keep the View as dumb as you can, keep the Activity just smart enough to handle its own life cycle and handle its own views, and communicate with its own controllers (plural!), and everything else should be written (hopefully test-first ;) ) in the java lib.
Using these methods our app currently runs about 60-70% of its code in the java lib, with the next update should take it to the 70-80% hopefully.
I would recommend that you use some kind of slot mechanism. Similar to what other MVP frameworks use.
Definition: A slot is a part of a view where other views can be inserted.
In your presenter you can define as many slots as you want:
GenericSlot slot1 = new GenericSlot();
GenericSlot slot2 = new GenericSlot();
GenericSlot slot3 = new GenericSlot();
These slots must have a reference in the Presenter's view. You can implement a
setInSlot(Object slot, View v);
method. If you implement setInSlot in a view then the view can decide how it should be included.
Have a look at how slots are implemented here.
In cross platform development sharing what I call a "core" (the domain of your application written in Java), I tend to give to the UI ownership of which view to display next. That makes your application more flexible, adapting to the environment as needed (Using a UINavigationController on iOS, Fragments on Android and a single page with dynamic content on the web interface).
Your controllers should not be tied to a view, but instead fulfill a specific role (an accountController for logins/logouts, a recipeController for displaying and editing a recipe, etc).
You would have interfaces for your controllers instead of your views. Then you could use the Factory design pattern to instantiate your controllers on the domain side (your Java code), and the views on the UI side. The view factory has a reference to your domain's controller factory, and uses it to give to the requested view some controllers implementing specific interfaces.
Example:
Following a tap on a "login" button, a homeViewController asks the ViewControllerFactory for a loginViewController. That factory in turn asks the ControllerFactory for a controller implementing the accountHandling interface. It then instantiates a new loginViewController, gives it the controller it just received, and returns that freshly instantiated view controller to the homeViewController. The homeViewController then presents that new view controller to the user.
Since your "core" is environment-agnostic and only contains your domain & business logic, it should remain stable and less prone for edits.
You could take a look at this simplified demo project I made which illustrates this set-up (minus the interfaces).

MVC on android: Model change and animation

After some thinking/reading (especially following series) I came to accept the following general rules for implementing MVC:
Model - set of simple dummy Value Objects, responsible for keeping the state. Model classes are Observable and notify Observers - i.e. views when changed. Model code could be android agnostic.
View - classes able to keep/update its visual state - based on android.view.View/ViewGroup family - by inheritance or composition. View classes are Model-aware, they receive update of Model's state and re-draw accordingly. All user-input listening code is delegated to Controller.
Controller - all user-input processing code in your activity/fragments. Controller updates the Model, which in turn, will trigger subscribed View update.
Sounds simple and certainly doable in most cases.
Now, consider for example:
Controller/Activity keeps track of 2 Model objects model1 and model2 and changes them based on some application logic.
View receives updates from objects model1 and model2 independently as per design above.
Now, suppose the View wants to show animation based on mutual transition of both model1 and model2 for which it needs to know changes of both objects at one time, or as a single event.
What would be recommended way of doing it, keeping mvc design above in place?
I thought about options:
Have a "SmartModel" which encapsulates both model1 and model2, make the mutual changes/transition and inform the View. I don't like this approach because Model becomes not really just "dumb" state representation, but also drags some application logic from Controller.
Have Controller inform the View about the changes it did on both model1 and model2. In that case neither model1 nor model2 need to implement ability to notify the View, i.e. there is no link between Model->View anymore.
May be there is much better option / I am missing something.
Any insightful suggestions will be highly appreciated.
I think the option 2) is similiar with MVP pattern, controller is kind of presenter to change the view for model.
Model View Controller, Model View Presenter, and Model View ViewModel Design Patterns
If you want to follow the strict MVC way, maybe you need to fire some change event to notify the View observers, so they can know what and how exactly the model changes, so they can do partial refresh and animation.

Categories

Resources