Pattern for notifying Activity of a network status code - android

I have many Activities that have several fragments. Part of the work those fragments do is to make authenticated network calls. It is possible that the token will expire. When that happens, I will see the 401 in the networking layer. What is the preferred method to communicate back to up the stack to whichever fragment initiated the network activity that it needs to initiate the logoff procedure? In other words, when the networking layer gets a 401, I want to communicate that back to the UI that the user needs to be log offeven though many other Activities may have also been invoked since then. This is often done via custom exceptions being handled in the app but I was wondering if there was a specific pattern that was preferred other than that. Something using Live Data perhaps?

You should separate in layers. Each layer should be responsible of a single task. There are many ways to do this, but you could use the MVVM Google approach which consists in:
M (Model): data classes and repositories that persist/retrieve them.
V (View): Activities/Fragments that observe data objects (LiveData) exposed by the VM and also call actions of the VM.
VM (ViewModel): Exposes actions, e.g. login, internally calls a Repository which calls the API (e.g. using Retrofit2), when it receives a result, it updates the data objects observed by the V.
Have a look at:
ViewModel
LiveData
Codelab

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.

Implement Redux with Android Observer/Livedata/Coroutine/Kotlin

Consider the Android app architecture that is recommended by Google: https://developer.android.com/jetpack/docs/guide
This architecture is based on ViewModels and Observables, therefore I would categorize it as "Model-View-ViewModel" (MVVM) architecture.
This is quite different to React-Redux. Whereas the Android architecture encourages bi-directional dataflows between Views and ViewModels, Redux enforces a uni-directional dataflow in a circle.
Moreover, the Android architecture keeps state in several ViewModels, whereas Redux enforces a centralized store.
Now my question is how to implement Redux with native Android libraries.
My first attempt would be:
Implement a centralized store as a Kotlin Singleton object.
The store provides a sendAction-method that takes an action, puts it in a queue and then returns quickly.
Actions are pure Kotlin data classes because they should not contain any logic.
Within the store, implement a Kotlin-Coroutine that picks up actions from the queue and dispatches them with a huge switch-statement.
Use a Room-database + some ephemeral state as a model. In particular, the ephemeral state controls which Fragment/Dialog is shown at any given time.
Ensure that the state is only mutated by the Coroutine.
Use observable livedata (androidx.lifecycle.LiveData) to re-render the UI whenever the Room-database or the ephemeral state changes.
Since observables are not enough to control an Android UI, I would also need a function that compares the current fragment/activity with the expected state, and e.g. trigger a FragmentManager transaction if a deviation is detected.
However, a few points are not clear:
How to keep activity/fragments in sync with the global state? Perhaps I would use a single activity and replace fragments as needed, depending on the current state of the store.
How can I implement both async + sequential action dispatching? Perhaps I would implement a single Kotlin-Coroutine that picks up incoming actions from the queue and dispatches them straight on the UI thread.
How can we ensure that the entire UI is re-rendered before new actions are dispatched? Perhaps I would stall the dispatching coroutine until there are no more other runnables in the queue of the UI thread?
You are right to say there are some limitations with MVVM.
Redux-style architecture tends to get called 'MVI' or 'Unidirectional' in Android.
There are some attempts at implementing this architecture in Android already that you can take a look at to help answer your questions:
MvRx
Mosby
In addition, this summary page
has a list of articles/libraries describing the approach.

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).

Can I use ViewModel to send data to the server?

Currently, I am using ViewModel to load a list of Shows in my app. Then, I display it in the main screen. It survives to configuration changes and does not provoke memory leaks since ViewModel has this features.
Now I need to do something a bit different. I need to log in a user making a network call to an endpoint using retrofit 2 and rxjava 2, he will type the email and password, and then will be redirected to the MainActivity. Second, I also need to update the user information, he types his new information and then I send to the server.
May I use ViewModel to log in a user or to update user information? If not, what sould I use instead?
What I need
This retrofit 2 call should survive to configuration changes, as rotating the screen, and it can not cause memory leak.
What I tried
Calling retrofit using enqueue() method in the MainActivity. Obs: This approach is not good because it puts to much things in the ui class, it provokes memory leaks.
Using static inner classes. Obs: It does not survive to configuration changes, as I need to cancel the task in onDestroy().
MVP seems fine to login a user.
You can check google sample project, specifically this class
https://github.com/googlesamples/android-architecture/blob/todo-mvvm-databinding/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskViewModel.java
Usually you would trigger the network operation in the model view, while the code for implementing the network logic is written in a different class (ApiManager for example), and then get the results in your ViewModel
LoginViewModel will have an object of some network manager class
When you click login, the viewmodel will call networkManager.performLogin()
Results are then passed to the viewmodel (RxJava is handy in here).
In your ViewModel do whatever processing you need when you receive the results

When to use Android Loaders

Loaders
monitor data source and deliver new results
After a configuration change : no need to re-query the data
I read the android guide about Loaders.
I read Alex Lockwood 4 parts tutorial . Tested his sample app too.
Tried to read the Google App for I/O 13, there's a Stream feature and reading its code find out it uses Loaders since it provides code to create a StreamLoader. Here is the Link
I suppose they use it to monitor for new data and add them to their view.
Same for Alex's app. There's an observer and when there is new data entries triggers a refresh for the UI.
So far it seems to me, Loaders are ideal choice for a "livescore" app. When there's a new update ( which means a new data entry ) it appears on your screen.
Maybe something like Twitter. New messages for you, custom Observer to notice for changes, custom Loader brings the data and an adapter to display them. No need to "pull-to-refresh".
But then again Twitter has its own RESTful API which kinda does the same job. No need for a pointer to the new data. ( don't know how they do it but I guess somehow the "push" new data to your device ).
So my question is :
Loaders are best option when we want to observe a data source and change our view so it will display the new data?
Are there any examples/app I can check dealing with that logic : monitor the data source -> get the data -> refresh UI
Any characteristic cases ( like the one with the "livescore" previously mentioned by me ) that when we have to deal with them we have to choose Loaders?
The second part of the Loaders ( configuration change, keeping the data ) I think its clear. No one want's to re-download an Image gallery when the user rotates the device.
Thank you and excuse my confusion
The best way I can describe a Loader is a Handler that is always on. Both Loaders and Handlers pass data between objects.
I agree with what you said about the "livescore" app.
The Loader monitors the source of their data and delivers new results when the content changes.
To answer your questions:
1) Loaders are best option when we want to observe a data source and change our view so it will display the new data?
A: Yes. if your data source is constantly updating. For example, like a stock-ticker app. If your data isn't constantly updating, then no, don't use a loader. For example, if your data source is only retrieved once, then there's no need for a Loader.
2) Are there any examples/app I can check dealing with that logic : monitor the data source -> get the data -> refresh UI
A: https://www.youtube.com/watch?v=3d9BeWqlfTk
Yes, they are what you want to use for the flow you're describing. Tangentially, there's also AsyncTasks and Services that have similarities.
AsyncTasks
Description (from docs):
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.)
Caution: Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change (such as when the user changes the screen orientation), which may destroy your worker thread. To see how you can persist your task during one of these restarts and how to properly cancel the task when the activity is destroyed, see the source code for the Shelves sample application.
If you specifically just want a wrapper to basic threading boilerplate, use an AsyncTask otherwise I'd suggest you use an AsyncTaskLoader if you need a general purpose way to run intensive operations in an Activity or Fragment. You get the same benefits from AsyncTask, but it handles lifecycle issues for you. There are also specialty loaders, such as CursorLoader that will are made to handle specific data sources and have conveniences for interacting with certain UI elements.
Services
Description (from docs):
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
You would use a service to handle data being pushed to a phone. Otherwise, the user would have to open your app to get any pushed data. Services do not interact with your UI. So a common design pattern is to use a Service to gather data from a server (whether pushed real time or if you poll) and store it in your database for use both when your app is opened or when not. There are many other use cases for Services, but this one is probably the most popular.
Conclusion
So no, you aren't required to use a Loader to load data or do long running operations on a background thread and pass the results (or progress) to your UI thread, but they are the best option for most use cases.

Categories

Resources