Alternative to passing activity to Repository - android

According to this image on the Guide to Android App Architecture, and some other material that I have watched and/or read, objects at a higher level of the architecture hierarchy should have instances to (and only to) objects that are lower in the hierarchy. For example, the Activity can instantiate the ViewModel and the ViewModel can instantiate the Repository. I also understand that the repository is supposed to interact with the data source and provide a clean API for all of the app to use. Additionally, the ViewModel (or even the repository for that matter) should never have an instance to the Activity that it is servicing.
In my app, I am using Firebase Cloud Firestore to store my user data, and I want to update my data in real-time. FireStore API provides a nice way to clean up the listeners when the underlying Activity Stops, that is the
addSnapshotListener(Activity activity, EventListener<DocumentSnapshot> listener method for the DocumentReference class. According to my understanding of the Architecture guide, all these listeners should be present in the Repository class. So to make the listener stop when the Activity stops, I'll have to pass an instance to the Activity into the Repository. This is not advised as if the activity configuration changes, it causes a memory leak.
The other solution would be to create the listener in the Activity class but that violates the Seperation of Concerns principle and in general makes the activity kind of clunky.
The third solution is I manually remove the listener from the Activity's OnDestroy() (or OnStop() whatever) method. But that seems like a bad idea because what happens if there are multiple listeners to the data that all need to be active at the same time? I'll have to keep track of all of them and all that seems like a lot of work that the FireBase API has already handled for me.
How do I go about this problem? Can the LifeCycle classes provide a solution? Or do I just screw the Architecture guide?

Interesting question and after looking at Handling Lifecycles with Lifecycle-Aware Components I can think of the listener being passed from the Activity/Fragment into the ViewModel and from there to the repository where you would be able to get the lifecycle events and act accordingly.
Unfortunately, because the repository needs to know about the lifecycle changes you can not have an entirely decoupled repository as it needs to know about the lifecycle events (LifecycleOwner).
Having this listener passed into the ViewModel or Repository doesn't seem too bad, although you may be able to use the ViewModel onCreared() since ViewModel is lifecycle-aware.
From the ViewModel.onCleared() you could call the repository to stop listening for snapshot changes. However, this would have to be managed manually but then you wouldn't have to worry about a reference from the activity in your repository.

Related

Bound Services in MVVM pattern

I'm working on an Android app (in Java) and trying to use Google's recommended application architecture, but I can't seem to figure out where services fit in to this architecture. I've done a lot of looking online and there is no clear consensus on how this should be done.
For context, my application communicates with a BLE device. I've created BLEService which extends Service that establishes the connection with the device, and provides methods send data to the device. The device can also send data back (and thus needs to notify the app when data is received).
My question is, where should the ServiceConnection reside, and how should it be stopped/started? From my research, there are a couple options that each have their pros and cons.
The Service is started/stopped in the Activity, the Activity observes events from Service. The Activity forwards the events to the ViewModel for processing. This pattern keeps all of the Android components together, but gives more responsibility to the View than I believe it should. The View should only be responsible for handling the UI.
The Service is stopped/started in the ViewModel (perhaps by extending AndroidViewModel). The ViewModel observes events from the Service and processes the events. This pattern is nice because the ViewModel is handling the business logic, however if Service implements its events via LiveData, Google states that the ViewModel must not observe LiveData. Another option is for the Service to implement events via something like EventBus, but there are a lot of people against using EventBus because it is easy to abuse. I have also heard that ViewModel should not have any Android-specific code in it for testing purposes.
The Service exists in some sort of Repository/Model. The ViewModel forwards its sends and observes events from the Repository/Model. This solution is nice because interfacing with a Bluetooth device does seem like it fits the intended purpose of what a Model is. However, it suffers the same issue that the ViewModel must not observe LiveData. I have seen Transformations.switchMap suggested in this case, which causes a LiveData in the ViewModel to be updated in response to a change in a LiveData from the repository. I'm not totally clear on using this strategy, or how it would function in my specific use-case. There's also the issue that the repository needs access to Context, and I have heard it's bad practice to hold on to an instance of Context. Furthermore, I have also read that a Repository should not hold on to callbacks from the ViewModel.
I'm sure there's no perfect solution, but if someone could point me in a direction of best practices, particuarly in my use-case, that would be immensely helpful.

Discuss using Kotlin Coroutines with MVVM?

I am using Kotlin Corountines with MVVM pattern and faced a problem: The data processing part is being done inside the ViewModel. While the repository seems not really necessary. When the application needs to call many APIs, the ViewModel will swell. What is everyone's solution to this problem? Thank you
The repository is needed, because in the case when you have a large app and gave too much responsibility to the ViewModel it's broke the separation of concerns principle.
Basically in the Andorids Guide to app architecture :
A first idea for implementing the ViewModel might involve directly
calling the Webservice to fetch the data and assign this data to our
LiveData object. This design works, but by using it, our app becomes
more and more difficult to maintain as it grows. It gives too much
responsibility to the UserProfileViewModel class, which violates the
separation of concerns principle. Additionally, the scope of a
ViewModel is tied to an Activity or Fragment lifecycle, which means
that the data from the Webservice is lost when the associated UI
object's lifecycle ends. This behavior creates an undesirable user
experience.
Instead, our ViewModel delegates the data-fetching process to a new
module, a repository.
And direct answer for your question:
Even though the repository module looks unnecessary, it serves an
important purpose: it abstracts the data sources from the rest of the
app. Now, our UserProfileViewModel doesn't know how the data is
fetched, so we can provide the view model with data obtained from
several different data-fetching implementations.
Basically, you can give all work to your ViewModel, but it's not recommended.
If you work/planning to work as a dev, maintaining your code, make it flexible to change and understandable for others is also important and usually, everyone appreciates this

Using Kotlin Coroutines to replace LocalBroadcastManager for Firebase messaging

When using Firebase Cloud Messaging on Android, it is often desirable to notify the current Activity of an incoming push notification. One of the recommended ways to do this has been to use LocalBroadcastManager to send an Intent from the FirebaseMessagingService implementation to the Activity (StackOverflow example answer).
However, as of version 1.1.0-alpha01 (2018-12-17), LocalBroadcastManager is deprecated:
LocalBroadcastManager is an application-wide event bus and embraces layer violations in your app: any component may listen events from any other. You can replace usage of LocalBroadcastManager with other implementation of observable pattern, depending on your usecase suitable options may be LiveData or reactive streams.
While it is highly likely that this class will remain available for a while longer, I would like to start cleaning up our applications anyway, so I want to migrate to something better before Google actually removes the old way.
Right now, there are two main roles that these local broadcasts have in our apps:
Update the UI with the new data from the push notification. The way this worked was that each Activity that cares about the incoming push data has a broadcast receiver that listens for the appropriate message and updates its own view data.
Force the user to log out if the server sends a notification to end the session. This works with each activity having an instance of a broadcast receiver that listens for a logout event, ends the Activity, and starts the Login Activity.
As I see it, these use-cases have issues with both of their suggested alternatives:
LiveData is easiest to use in an Activity or Fragment as part of a ViewModel. However, ViewModel is only meant to be used from those classes that directly deal with the UI. Accessing the ViewModel from within the FirebaseMessagingService takes an ugly hack and is a really bad idea from an architectural perspective. Also, different activities and fragments have different ViewModel objects, and I don't want the service to need to access them all.
I can create a Kotlin object (a.k.a. Singleton) with a bunch of LiveData properties, have the FirebaseMessagingService update those LiveData objects from the incoming messages, and have the Activity observe those changes and copy them into its own ViewModel's LiveData properties. The problem with that is twofold: first, it requires me to have two identical LiveData objects for each piece of data, one in the ViewModel and one in the object; and second, it doesn't help me with handling the "log out event", because LiveData is meant to handle changing data, not listening to a stream of events. (I may be able to handle the second issue using this LiveData Event Wrapper, but that still feels like a bad hack over something that isn't meant to work this way.)
While reactive streams, such as RxJava, will probably do what I need, I already forced my team to learn Kotlin, Android Databinding, Android ViewModel, and a bunch of other new stuff in the last few months, and I don't think they can take much more. RxJava is also a large thing to add for just this one use, and we have no plans to rewrite the entire application to take advantage of it in order to justify its addition.
One suggestion I found was to use Kotlin Coroutines with Channels or Flows. These can be used very similar to reactive streams, but (unlike RxJava) are intended to be used with Kotlin and benefit from Kotlin's improvements over Java. This option is especially attractive now that Google has announced that they are focusing on Kotlin for Android development instead of Java.
While this seems to me to be the best option, I have not managed to find any feedback from others about whether it works and if there are side-effects and/or pitfalls to such an implementation. The only thing I found was an open issue on the kotlinx.coroutines repository about the need for providing an example of an application like this. While I'd love to contribute such an example, I don't think I know enough about it to create a good example, and I don't want my production apps to be the guinea pig. I also don't know whether it is better (or proper) to use explicit couroutines with Channel or to use suspend with Flow for this case.
In summary:
Are Kotlin Coroutines and their associated concurrency structures a good way to handle communication between Android Service and Activity?
If yes, which Kotlin type makes more sense to use, Channel or Flow?
Coroutines don't really help with the handoff of data from one software component to another. They help with the processing multiple units of asynchronous work using syntax that appears as if they were synchronous. That's the bottom line for coroutines. They're analogous to async/await syntax in JavaScript. While you might use a coroutine to access data from asynchronous sources, it doesn't give you any primitves to proxy that data on to other components.
LiveData probably works just fine for what you're trying to do. Don't conflate ViewModel with LiveData - they solve different problems. While you're correct that ViewModel should only be accessed by code that deals with UI, that guideline doesn't extend to LiveData. It's perfectly reasonable to expose a LiveData that reflects current data from FirebaseMessagingService that is later picked up by a ViewModel, transformed, and passed on to a view. This LiveData could be a singleton, or obtained via whatever dependency injection infrastructure you choose.
Bear in mind that LiveData is really only supposed to be used for managing changes in state. It's not a "stream" of data that your app can listen to. You will need to make sure that your infrastructure is state-based in order for this to work out well. FCM itself is not state-based, but if you want your views to respond to messages from FCM, you'll need to retain enough context between each message to make sure your UI responds consistently to new messages (or the lack of messages altogether).

ObservableField or LiveData? Which one is the best?

I have been testing Livedata and AAC in general.
What is the core difference between LiveData and ObservableField?
Which one is the best and when should I use one over another?
The core difference is that ObservableField<T> is not lifecycle-aware and hence there cannot be any automatic subscription management. While LiveData<T> is lifecycle-aware and solves tons of headaches with subscription management when it comes to Activity/Fragment lifecycles.
There is no one way to answer what is the best to use. It is a personal choice, but I would suggest using LiveData<T> just to save yourself some time and avoid potential issues in the future.
Both LiveData and Observable could be used alternatively. LiveData is lifecycle aware and hence will notify only the observables which are "active".
Quoting official documentation on https://developer.android.com/topic/libraries/data-binding/architecture#livedata
Unlike objects that implement Observable—such as observable fields—LiveData objects know about the lifecycle of the observers subscribed to the data changes. This knowledge enables many benefits, which are explained in The advantages of using LiveData. In Android Studio version 3.1 and higher, you can replace observable fields with LiveData objects in your data binding code.
As mentioned both are usable for UI binding interchangeably. LiveData is a quick method but if you want more control on the binding Obserable is a way to go with.
Quoting official documentation on https://developer.android.com/topic/libraries/data-binding/architecture#observable-viewmodel
There are situations where you might prefer to use a ViewModel component that implements the Observable interface over using LiveData objects, even if you lose the lifecycle management capabilities of LiveData. Using a ViewModel component that implements Observable gives you more control over the binding adapters in your app. For example, this pattern gives you more control over the notifications when data changes, it also allows you to specify a custom method to set the value of an attribute in two-way data binding.
We get options to customize the binding in case of an Observable which might be helpful in some case.
Personal preference is to go with LiveData. In case some some customization or more control is needed on the binding go for Obervable
Similarities
Work well with data binding
Bound views automatically unsubscribe when in the background
POJO classes can also subscribe to changes
Differences
LiveData allows for POJO subscribers to be lifecycle aware. Meaning that if you have a property B that you want to update when A changes, you can opt to not receive updates when the attached view is inactive. This saves resources.
Background thread updates of ObservableField<T> are immediate. MutableLiveData.postData is delayed.
Values of LiveData<T> and ObservableField<T> are always nullable, but the primitive implementations ObservableInt, -Float, -Boolean etc are non-nullable.
MutableLiveData<T> doesn't take a constructor value to set on initialization.
When to use what
Do you have external events that may trigger cascading data change in the ViewModel when the app is in the backgrond? You should probably go for LiveData
Do you require value update on background threads to be immediate*? Use Observables
None of the above requirements? You can't go wrong with either but ObservableField is a simpler class.
*) "Immediate" in the sense that a get directly after a set/postValue is guaranteed to return the value you just set. None of the types are of course immediate when it comes to UI update.

Synchronizing data between active activities / fragments

I have to solve a theoretical problem and just want to get feedback about the best pattern / practice to solve this in android.
Task:
An app could have several activities / fragments showing a list of objects. If one object is present in more than one list at the same time, I want to synchronize changes to this object. So e.g. if I delete the object it should disappear in all lists.
The restricts are that
I don't know which lists are currently instantiated
Every list has it's own object instance. Data is not shared directly between lists
My solution so far would be to
define a Storage class which provides methods for data access
create a custom Application class and instantiate the Storage class with the application context (which is needed for e.g. content provider access)
the Storage class defines a Listener where each activity can register itself
if an activity modifies an object, which it has to do through the (Application) Storage, the Storage class sends an event to each activity / fragment registered so they can adopt the changes.
Does anyone know a better solution for that? And is my solution conform with the android lifecycle?
Thanks a lot for every kind of useful feedback
If you want to deal in Object then read up on implementing Services and Binding to them. You can provide all your objects with your own API methods and return values. If your data fits into a data cursor model, then you should read up on building your own ContentProvider. It has data observation built in and all the Adapters support it already.
Your solution seems pretty good. You could use an EventBus like Otto http://square.github.io/otto/ to send an event to all your activities/fragment when an object is modified.
If you insist on maintaining the separate lists in separate Activity/Fragment instances, then you will be prone to lifecycle problems (you might miss an object modification event while you're paused or something). Otto or other EventBus libraries might help.
However, I think it would be much simpler to host all those lists (and their possibly-shared objects) in a local bindable Service. Each Activity/Fragment can then simply bind/unbind to it in onCreate/onDestroy, thus guaranteeing an up-to-date view of those lists.
See http://developer.android.com/guide/components/bound-services.html
Another similar solution would be to host all those lists in a retained Fragment. Using retained Fragments would be simpler than a Service because you don't have to write all the bind/unbind code. However, retained Fragments might not work as well as a Service if you have multiple Activity components that need access to the same lists of objects.
Yet another hacky solution is to just host all those things in the Application instance itself (effectively a global variable). Then your Activity/Fragment code can just call ((MyApplication) getApplication()).getFooList() to get to those objects.

Categories

Resources