RxJava data from DB with onscreen list - android

I've just begun to learn RxJava and I'm a little bit lost.
My scenario is the following: A local NoSQL key-value database where I store some data. The problem is that the endpoint can add data to this DB and also the user can delete some of it.
I'm displaying this data as an on-screen list (RecyclerView).
I'd like to know what is the best approach to always know what's the most up to date data from the DB in a single place so I can update the UI accordingly.

What you're looking for is a way to create an Observer, meaning to transform DB changes events to Observable.
So you will have 2 kind of streams:
One that act on the DB and changes data (update/delete) triggered upon various events (push/cloud/user clicks) , those changes will trigger DB change event, that in it's turn, will emit events on an Second stream that represent DB changes event.
Then in your UI, you can react to the changes in Rx way (responding to the stream of DB changes events).
In order to create the DB changes Observable, you need to learn about hot to create Observable from async events (can be done using Subjects, or if you are integrating with some DB and you have DB changes events, you can 'wrap' it with Observable using fromEmitter(), you can learn more about it from this blog:
https://medium.com/yammer-engineering/converting-callback-async-calls-to-rxjava-ebc68bde5831#.z1cj7ayhr

One way to approach it would be to put a data service between clients and the data store. Make that data service an Observable. Allow anyone who is interested in being notified when data changes to register with the data service.

Related

Logic to update network requests using Work Manager

I have an application which fetches data from an API. SO basically, right now, the app works as such:
If connected to the internet, fetch data and use Android Room to store for offline use
If not connected to the internet, check if data exists in Room. If exists, display it. If it doesn't exist, display an error message.
I did some research online on how to implement an efficient offline storing policy and Google suggests to use Work Manager to queue requests and then send it when connected.
I actually want to know how to implement this ? (not the code but the logic, i.e should i schedule requests everyday to the API or every time it's connected to the internet ?)
If someone with experience with offline apps could help would be great.
My network requests are done through Retrofit and i already create a class that perform calls to the API.
Keep in mind WM (work manager) is designed to perform operations when certain conditions are met (e.g.: the user has enough battery, the display is off, etc.). So this may end up with your data not being updated when you need it. WM is good for operations you want to happen but are not critical to occur "right now". I'd say always use the Room DB as the single source of truth. If the data is in room, show it, if it's not, fetch it, if you can't, well, you tried. Send a message to the user. You can use a NetworkConnectivityListener to monitor connectivity and check if you have a pending query (you could store the parameters of this query in your Room database in another table for ease of use). So you'd query the DB, obtain the pending queries (if any) and execute them, update the data, and let the ViewModel/Repository decide if there's a context to show this data (UI).
I feel like you are very close to achieve what you need.
So in other words:
UI: Observes its viewModel for some sealed class xxx state to tell it what to do (show an empty list, show an error, pass data to a recyclerview adapter, etc.).
ViewModel: Using its viewModelScope.launch { ... } will call a repository.fetch(...) or similar. Your viewModel will fetch this data when the Fragment tells it to do so (e.g. the user pressed a button) or on some lifecycle event (onStart for example).
The Repository in this case normally exposes a flow (if you can use the experimental api) or a suspend function that can perform the following actions (that can vary depending on your business rules)
If the data is available in the Database, return it immediately.
If the data is old (or we still want to refresh it), then perform the network API (if there's connectivity to do so). If there's No connectivity, you could store this "pending" query in the database for later. You could also check if you have a pending query before doing any of this, perhaps it's outdated or perhaps you need to execute it.
In any case, once the query goes through, you insert the results in the database, and call the same method you used in step 1.
Don't forget to update your "pending" query if you had one (or if you use this).
With WorkManager, you could schedule the "fetch data from API" part to happen at some point (so your data will be kept more up to date), but I all really depends on the use-cases you have.

Understanding reactive

Recently kotlin flow is gaining a lot of attention. I have never done any reactive programming before so i thought now is a good time to learn it. Even though I have access to books and some articles I could not understand how to integrate it say on an existing app that does not have any rxjava. I tried looking for some sample but the only thing they would give me is very basic. Im really confuse about this reactive programming thing. For example, I have a list that I needed to get on database. Why would I use flow to get that data? If I visualize it as streams, that would give me one data each. While if I get that list I could get the whole list without waiting for each streams to come if I had use flow. I read a lot of articles about this kotlin flow, even rx java. But still, I wanted to understand why streams and how is it any different from other way like the example I just gave?
For example, I have a list that I needed to get on database. Why would I use flow to get that data?
Well, that depends entirely on what you are using to access that database and how it uses Flow.
Let's suppose that you are using Room from the Android Jetpack. In that case, you can use Kotlin coroutines in two ways, via suspend functions and via Flow:
#Query("SELECT * FROM stuff")
suspend fun getStuff(): List<Stuff>
#Query("SELECT * FROM stuff")
fun getStuffNowPlusChanges(): Flow<List<Stuff>>
In both cases, Room will do the database I/O on a background thread, and you can use coroutines to get the results on your desired thread (e.g., Android's main application thread). And initially, the results will be the same: you get a List<Stuff> representing the current contents of the stuff table.
The difference is what happens when the data changes.
In the case of the suspend function, you get just the one List<Stuff> from the point when you call the function. If you change the data in the stuff table, you would need to arrange to call that function again.
However, in the case of the Flow-returning function, if you change the data in the stuff table while you still have an observer of that Flow, the observer will get a fresh List<Stuff> automatically. You do not need to manually call some function again — Room handles that for you.
You will have to decide whether that particular feature is useful to you or not. And if you are using something else for database access, you will need to see if it supports Flow and how Flow is used.

Combining different sources in RxJava MVVM (FCM, Networking, ROOM)

I have previously used MediatorLiveData to combine results from FCM, Room and Networking in my Repository. It worked well. However, now I want more complexity and some additional bonuses from RxJava. This is why I have decided to use RxJava this time. I can combine Room and Networking with Observable.concatArrayEager(my _observables). However, I don't now how to do that after FCM pushes value, and how should I notify my main observable after new changes occur? No examples on this issue whatsoever. It is crucial part. I receive FCM in my BroadCastReceiver and then notified my repository's livedata, which notified my MediatorLiveData... How to do that with RxJava? Would really welcome any advice, because it is really important issue.
IMHO, you don't need to combine data from different sources.
Using the database as your single source of truth is definitely easier.
Room supports Flowable like:
#Query(“SELECT * FROM Users WHERE id = :userId”)
Flowable<User> getUserById(String userId);
Each time there is any updates to the table Users, Room will emit the updated user automatically once you subscribed.
The following approach may help you:
In you Activity / Fragment, subscribe to the Flowable.
Once receiving FCM notification, call network api and update the db.
Do with the updated data.
Anyway, if you need to combine sets of items from different Observables, you can use zip.
The concat operator emit the observables in the order specified, that means the second observable won't begin emitting till the first observable finish emitting objects.
But with merge operator you can combine as many observable you want into a single observable. for example:
Observable.merge(dbObservable, webObservable, fcmObservable)
.subscribe(item -> System.out.println(item));
P.S: In case you want to fetch data from a data source and keep it up-to-date using fcm you can do this:
fcmObservable
.startWith(dbObservable)
.subscribe(item -> System.out.println(item));
These are just few pattern available, as always there is nothing impossible in RxJava, based on what you want to do there is always a better RxChain for the job!

Update firebase database after specific time

I have a data field and time field ,user Enter data and time
After Writing data on firebase realtime Database I want to reset data field and Time Field to 0 after The specifed time in Time Field
I read about cloud function but I don't know to solve my problem
I'm new to firebase and it's cloud function Please help...
Data field will contain somedata
Time Field Will Contain data like 20 ,30 or 40 which represent time in mins
so after writing both to database
say if time field contain 20 ,so after 20 min to writing data in database, it should be reset to 0
Thanks in advance
The scenario you describe could be achieved in two ways. In my opinion, one can be cheaper and easier (no function involved but need to add some logic and a query to data on client side) if you could implement it which depends on your case.
Not the cheapest one: Schedule (cron type jobs) to scan your database regularly and check for the specified time and reset your data if condition is met. And this requires you to use Firebase functions and cron type services to configure it.
The cheaper way (although dependent on your case) in my mind would be to set your logic client side, so whenever a user is navigating to that data , check for the time and if condition is met reset the data client side without client noticing. This way, you don't need to set up functions, and you are not performing anything as long as no client has gone there (wherever that the data your mentioned is used in your app) Just keep in mind that this depends on whether you can have such scenario or your data has to be update regardless of users interaction with it. I have managed to redesign stuff whenever I have come across a case that needs periodic updates, etc.
More info on second option:
Imagine your users are checking for an order which can expire after some time. Your intention is to reset data when expiry time has arrived. Instead of resetting data via functions, etc, you can write logic so that whenever a client queries the orders, you check for expiry time and if expired, you perform what has to be done there and then, in addition to making sure your client won't see the expired order. Hope this makes it more clear. It's sort of a passive way of updating your data in db.

How to define callbacks from SQLITE to Android Activity

I want to write a callback from sqlite database to android activity. Currently i am inserting some data from the webservice in to db and then set it to listview.
I am running a service in the background which will continuously check for the new data. If there is new data it will update the database.
My prob is how to define the callback onupdate from sqlite to activity.
Any help will be appreciated.
You should be able to achieve the result with observer pattern.
Your activity will implement an custom interface like RefreshableOnDBUpdateTrigger
in which you will re-load data from DB using standard DB querying mechanisms.
In your DB update class, you can call RefreshableOnDBUpdateTrigger.update() method which is essentially the method of your activity instance which fetches updated data from DB.
Refer observer pattern for implementation details.
This would require user-defined functions, which are not supported by the Android database framework.
You have to call these callbacks explicitly in your database access code.
Another option to the interface callbacks would be to use an Event Bus. The DB code fetches data and then posts an event with the data. Any registered classes would receive the event.

Categories

Resources