aerogear / offix-android

Apollo GraphQL offline extensions for Android Platform
https://android.offix.dev
Apache License 2.0
37 stars 16 forks source link

Creating the starter Android Library #41

Closed harshithdwivedi closed 5 years ago

harshithdwivedi commented 5 years ago

I think that we should start working on the android library that has the offline part implemented. I'm outlining the basic structure that I think would work, feel free to add your suggestions as needed.

The enqueue method

Our enqueue method should be an extension function on the Apollo Client and should take in 2 parameters :

  1. Mutation Object
  2. Callback for UI binding
fun enqueue(mutation : Mutation, callback : ApolloCallback){
    if(online){
        this.enqueue(callback)
    }else{
        //Save to db and schedule a worker task
    }
}

Different user flows

The library will need to act differently based on the following use cases :

  1. The app is in the foreground after making the call: Keep listening for network change and make a network call as soon as the client comes online. We can get access to the Context object by registering a Content Provider to initialize our library when the app starts. See : https://bitbucket.org/pitechbros/androidlibrary/src/development/library/src/main/java/app/pitech/event/provider/PipelineProvider.kt

  2. The app is in the background after making the call : Schedule the WorkManager call immediately after the app is closed to retry the network call after "X" amount of minutes.

Language to be used

Personally, I think that this would be super easy with Kotlin as we can use extension functions to add capabilities on the Apollo library easily while making the library interop with java easily. https://kotlinlang.org/docs/reference/extensions.html

@wtrocki feel free to provide your suggestions here.

Design Pattern

MVVM/MVP I personally suggest using MVVM but feel free to look around and see what suits you the most.

UI bindings

We don't need UI bindings when the app is in the background, so we can leave it for now and come back to this later.

Lavanyagaur22 commented 5 years ago

Alternative :

We can create a custom Interceptor of our own. The user would only have to add our custom Interceptor to the apollo client which he/she can make from the app. After that, we will check the network status of the client. If it is offline, then we can save it in DB and schedule work manager for retrying it after some interval of time. If it's online, then we will make a call as usual.

We can get the reference to the context object as suggested you above.

@wtrocki @harshithdwivedi WDYT?

harshithdwivedi commented 5 years ago

Hm, this sounds like a good idea on paper but it'll prevent us from doing any UI bindings later on since we aren't providing the developers with a callback.

wtrocki commented 5 years ago

I had some experience with this and we initially have done global listeners which were detached from UI. This meant that people needed to kinda have a single place in the app to handle notifications etc - like snack bars etc.

Global one is really needed and we cannot avoid having it because of original activities that could trigger the change may not be available anymore.

UI binding side is a little bit more complex and we struggled with this to be implemented. It is simply because mutate cannot return anything else than just expected objects. The only chance to do that is to return an error, but then the cache is not updated. This is a very hard issue that took some time to get right.

The global listener will be the easiest and most required. UI should not be stuck when offline change is applied (we should return something). This also messes up optimisticResponses. Implementation wise this is not that complex but the number of problems and testing required to do it.

TL:DR - global one are the safest now.

harshithdwivedi commented 5 years ago

@wtrocki can you outline a bit more on what you mean when you say global listener? Is it something inherent to android or is that related to Apollo?

wtrocki commented 5 years ago

The global listener is a listener for offline updates that will be mounted to application context instead of just relying on execute a method for the graphql stuff.

It will be something to let people know that offline change was replicated.

wtrocki commented 5 years ago

Lots of really good work. Can we close this issue now or is there anything left

harshithdwivedi commented 5 years ago

We can