Proper MVVM Connectivity Management & Data Caching Policy - android

I'm developing an Android app (using MVVM) and I'm trying to implement Room DB caching for one of my models fetched from a REST API through Retrofit.
My question is: Is it correct to have my caching/fetching logic in the Repository as well as the network connectivity checks (using ConnectivityManager) to dictate whether to fetch data from the network or a Room DB cache? I'm asking since ConnectivityManager requires Activity-level Context to be instantiated and having it passed all the way down to the Repository doesn't sound correct to me in MVVM terms (and I'm not sure if it could work since I want to use ApplicationContext to instantiate it and I haven't seen people doing it like that).
I also don't want to try making a request to test connectivity because that'd ruin the entire purpose of using the Room DB as a Single Source of Truth for all my data and would be a rather useless request.
The only other way I might implement such connection checks and handle all the possibilities is through the NetworkBoundResource unofficial code excerpt from Google but I'm wondering if anyone else has a better solution. I'm also planning to save the last fetch time from the API as a property in my Repository (and update it after each API call) but I'm afraid that could lead to some tight coupling and overall shaky architecture. If anyone has a solution to how I might go about that, it'd be very helpful.
I'd be willing to experiment a bit but I don't think I can get in that headspace without mucking everything up.
Thanks in advance!

Related

Can a use case be called in data layer in context of Clean Architecture?

I have read a couple articles about clean architecture concepts here and here and others.
I think I understand what is going on but they didn't solve the question that I have.
I wonder if a use case can be called from data layer. if so, how? if not why?
UPDATE:
what I am trying to do is to track what is happening during each usecase with a event usecase. Sometimes, I need to collect those info in data layer as well.
Let's say I have
CollectEventUseCase
for that event usecase. I want to track if a person data lookup from network was fail but successful from database during the LookupPersonUsecase and I want to collect that information that lookup was failed from network but successful from database, is this a bad idea to call CollectEventUseCase in data layer? is this okay solution to this case? or whatelse should be the right approach?
Short Answer - No, in a CLEAN architecture the data layer should not be calling through to a use case as it would be breaking the separation of concerns. Data layer should only be concerned with data, not business logic which lives in a use case.
Long Answer
One main reason for implementing a CLEAN architecture is for implementing separation of concerns, meaning each layer addresses a specific concern in your app. Expanding on the photo in domain layer Android documentation, an app architecture might look like the picture below.
Where the domain layer would contain all of the business logic for presentation and use cases which can communicate with different sources in the data layer.
The data layer exists to serve as an abstraction over where data is coming from and that should be its only responsibility. Most apps data layers are fetching data from the network and then caching that data in a local database. So to best separate the concerns, a use case should only be concerned about interacting with different sources from the data layer and any business logic.

For accessing data offline, better to use Room library or HTTP cache-control?

I looked into solving the problem of accessing data offline in Android and came across Room library and HTTP cache-control. I already have all of the Retrofit / OkHttp responses done in my app. Which is better to implement when there is no Internet connection?
It greatly depends on the requirements of your app.
Room allows you to save and organise the data. Specific queries and extraction of distinct objects is very powerful if needed. Besides that you can be sure the data won't be deleted, when the device needs storage and clears the cache folders. One problem however is data integrity, which would require some sort of synchroniser between your app and the backend server. I would advise you to use Room if you do any sort of data manipulation and/or want to offer certain and reliable offline user experience.
HTTP CACHE is simpler and a quite straightforward solution. You only need to add a interceptor to your OkHttp client and you are ready to go. This would be the solution if you app's main purpose is simply displaying data.

Should all data be exposed via ContentProviders?

So I come mostly from a web background and I'm trying to learn the architecture of android apps. Trying to grasp a proper understanding of content providers.
What I think I'm understanding is that content providers are pretty much your middle man between the activity/services and your data (DAO of sort). I also think that content provider are also to provide other applications access to your data (almost like a web service?)
What I'm not really getting is, what if you did not need this data exposed to other applications? Do I need to bother with content providers and all the uri defining etc? If not, is there a name for this ... pattern? (or lack of) Or am I better off just using ContentProviders and just accept the added benefit of exposing this data to other apps?
I know eventually I will want to sync data between the app and a external database. I saw a google IO presentation supporting the pattern of using a content provider for RESTful communication. But for the time being, I'm just trying to get comfortable with basic static data. Then hopefully swap it out to data from a REST service down the line once I get it.
Hope I'm not completely off here. Thanks.
Although it says that content providers are nice for sharing content they also give you a couple of other things free!
The best thing about content providers is that the system handles the threading issues for you :) when I ported my app over to Honeycomb i got lots of database errors (mind you ones that couldn't previously exist in gingerbread) I wasn't handling the access on different threads properly.
I quickly put a content provider on top of my database and well.. never looked back in that regards, it seems much easier once you've setup your content provider the code throughout the rest of the app is much nicer and you don't have to worry about concurrency
As written in the specs, and as you mentioned :
Content providers store and retrieve data and make it accessible to all applications. They're the only way to share data across applications; there's no common storage area that all Android packages can access.
So if the data you are storing should not be accessible by other applications there is no need to bother with ContentProviders. As you can see on Android Data Storage there are several ways in which you could store your data.
My opinion is that in your case, for usage of REST Services, and data that is not to be shared with other application you should use SQLiteDatabase. You can find a good example SQLiteDatabase example here.

Optimal RESTful method for web service

I'm looking for guidance on the optimal REST/Json method to use for our production app. The scenario is app <-> web service <-> server (lighttpd or nginx) <-> our program <-> sql database. The data traffic between Android and server per call is pretty small. There is no significant CRUD on the client.
I've seen the Google IO 2010 presentation (http://www.google.com/url?sa=D&q=http://dl.google.com/googleio/2010/android-developing-RESTful-android-apps.pdf) with the 3 proposed patterns (Service API, ContentProvider API, ContentProvider API and a SyncAdapter). Have briefly looked at the iosched 2010/11 app though haven't worked out which of the 3 methods (if any) it implements.
We want to offer our app users a seamless experience by managing state to support various types of interruption or failure. How can we determine what is the optimal REST method for our need? Are the Google suggestions overkill?
Thanks in advance!
The correct answer depends on how much data and what operations we are talking about.
You wrote: "There is no significant CRUD on the client." If you are only using the "R" from "CRUD" (=read data from somewhere), AND if your app doesn't really depend on it, AND you are not synchronizing content frequently, you may even get away with fetching it form inside your Activities.
However you may want to explore the Service API from the get-go anyway. Like that Google presentation said, your Activity can be shut down at any time, so if makes sense to put your REST methods somewhere where they have a better chance of completing.
Please consider the future needs of your app, its use cases, and then look at the available options.

When to use a Content Provider

I understand that Content Providers are made to allow publicly sharing data between applications. However, I'm wondering if anyone has thoughts about making a Content Provider to use just within your own app. Would there be any advantages to doing this? Any disadvantages?
In the past I've just implemented the SQliteOpenHelper to access data from my database, but I'm considering creating a Content Provider. I feel like the URI approach to requesting data is clear and concise. On the other hand, will using a Content Provider just for my application be redundant ( since within it I will have a SQliteOpenHelper class ) and more work than I need?
I would argue it is definitely a good idea to use a ContentProvider even if you don't intend to make it public.
It's good practice to provide the extra level of abstraction over your data to make it easier to change internally. What if you decide to change the underlying database structure at a later time? If you use a ContentProvider you can contain all the structural changes within it, where as if you don't use one, you are forced to change all areas of the code that are affected by the structural changes. Besides, it's nice to be able to re-use the same standard API for accessing data rather than littering your code with low-level access to the database.
Also, there is always the chance that you might want to expose your data in the future. If you don't use a ContentProvider up front, it will be much harder to retrofit it in at a later date.
Then, there's the other parts of the Android where ContentProvider's are required/recommended such as when using SyncAdapters and if you want an App Widget that involves data access for instance.
In summary, there is very little overhead involved in writing a ContentProvider up front (once you have learned the API which is a good idea anyway) so it makes sense to do so, even for private data.
If you are not planning to share data, don't think about Content Providers. They are powerful but hard to write and it will be just silly to implement them if you are going to use them internally.
However, I'm wondering if anyone has thoughts about making a Content Provider to use just within your own app.
Of course... for instance, for an old TODO list app I wrote, I had to write a content provider to allow other apps retrieve and access the tasks states. It was part of the requirements, but more than that it made sense and made the app nicer.
Take a look at the MOTODEV Studio for Eclipse. It is a development environment that extends Eclipse. They have a tool where you can automatically generate a content provider for a database. If a content provider makes it easier to access your data and it doesn't have a significant impact on performance go ahead and use it. In most scenarios this will be the case.
In short,Content Providers helps in managing your data effectively. I would suggest to use them for the following reasons.
It acts as an abstraction layer between your UI and database. You can implement data validation in ContentProviders to validate the data entered by the user. It also lets you to modify the structure of the database without touching the UI and other parts.
They play along nicely with other android framework classes like SyncAdapter. For eg., you can automatically refresh a list, when a value in a database changes using ContentProviders along with CursorLoader. Without ContentProviders you have to implement a lot of functionalities like these on your own.
We can safely expose our private data to other apps. Using ContentProviders will allow us to share our data easily and safely with other apps.
So even if you don't need any of these functionalities now, you might need them in future and its good to go the extra mile and implement them right now.
I agree ContentProviders are a little difficult to grasp but they are definitely helpful, even if you want to use them internally for you own app. The best thing about it is that you can customize the contentproviders for suitable URIs.
Here's a scenario where you may have 5 tables in your database, but you need to join a few of them in certain orders before using them. And make a content URI for each of these joins. You could then each use these URIs as a table :)
I suggest you go ahead with Content Provider, you'll be amazed to see how powerful it is.
In my view point, the content-provider comes with plenty of advantages leave alone just sharing data with other apps. If you need to synchronize with the server using a Sync-Adapter, use google cloud messaging, auto update the UI when the underlying data in the DB changes using Loaders, implement search, use widgets... then the content provider is for you.
I prefer you follow the guideline on because one day you may need to implement some of the above features attached to the content-provider
By the way, you can quickly build you database and CP in less than 5 minutes using content provider generator
As said in documentation:
Creating a Content provider
You don't need a provider to use an SQLite database if the use is
entirely within your own application.
So why bother developing this overhead? You want easier and faster development, right? So one layer of abstraction (SQLiteOpenHelper descendent) is enough.
See Occam's Razor
Do not make an entities without very good reason.
Using a Content Provider can help in an additional level of abstraction - Putting it within your own application make add a significant development time to your project. However if you are using it to share data, application settings or configurations across multiple applications then the Content Provider is your choice.
Watch your security levels and I would recommend using SQLcipher to encrypt data-at-reset (DAR) if your Content Provider is writing to SQLite. (I've used a content provider in a few solutions and provided the ability to take a live "snap shot" of the operational values for debugging and testing.)
Do not use content provider if do not wish to share data with other apps. Use simple sqlitedatabase to perform database operations. Be careful while using content providers for storing confidential data because your confidential information may be accessed by other apps

Categories

Resources