Apollo-android: Add support for Room (Android Arch Components)

Created on 31 Jul 2017  路  23Comments  路  Source: apollographql/apollo-android

Room requires that model class to be annotated.

See https://developer.android.com/topic/libraries/architecture/room.html

Discussion

Most helpful comment

It's not totally crazy to convert to and from Apollo's generated objects and Room compatible objects. A bit of work. We're doing it now - when we have time we might try to improve it by autogenerating the converters, maybe, HMU if anyone else has gone this route

All 23 comments

Is my understanding correct that you would need ability to annotate every field?

Yes. It would look like this.

@Entity
public class User {
    @PrimaryKey
    private int uid;

    @ColumnInfo(name = "first_name")
    private String firstName;

    @ColumnInfo(name = "last_name")
    private String lastName;

    // Getters and setters are ignored for brevity,
    // but they're required for Room to work.
}

Is there any reason to use Room instead of Apollo normalized cache?

@sav007: We're using it mainly so that we can do custom queries to the data.

Couple questions for you:

  • how you are going to handle migration from one version of generated model to another? (All models are generated from queries in *.graphql files). So lets say you added or removed couple fields, how migration will look like?
  • how you are going to support fragments, inline fragments, custom scalar types, directives?

Migration could be written manually using Room (https://developer.android.com/topic/libraries/architecture/room.html#db-migration). For our use-case, we just drop all the tables whenever we upgrade the database.

For custom scalar types, there are Type Converters for that (https://developer.android.com/topic/libraries/architecture/room.html#type-converters).

Can you elaborate more on fragments?

Fragments:
http://graphql.org/learn/queries/#fragments

Inline Fragments:
http://graphql.org/learn/queries/#inline-fragments

Directives:
http://graphql.org/learn/queries/#directives

My concern here is that before jumping into adding support we have to consider all edge cases and how to make it right.

  • How Room supports list of scalars?
  • Any entity should have ID?
  • What if query doesn't request ID or if GraphQL model doesn't have ID field in type declaration?
  • Do we need to take into account sub-query arguments for relationship between models?

How this simple query will be mapped with Room?

  shop {
   products(first:50, query:"Test") { // doesn't have id
    pageInfo { // doesn't have id
      hasNextPage
    }
    edges { // doesn't have id
      cursor
      node {
        id
        title
      }
    }
   }
  }

This should more bring up the discussion of allowing someone to declare own data models. We gave up in it due to complexity previously but is there anything blocking external pojos?

"Back in future" again back to support generating interfaces? We dropped this idea some time ago as it was sooo complicated on user side

We can try it again, not sure if it's going to be something good.
@dannyroa so if instead of generated models as POJO objects you will get bunch of interfaces, will it resolve your case?

@digitalbuddha we should try manually take any generated model (some complicated model with fragments, inline fragments etc) turn it into interface and then try manually implement it, before touching generation module.

@sav007: Yeah, interfaces should work and the implementing class will have the Room annotations.

What's the word on this? Is room support still being considered?

@speppers 馃挴

This would be awesome, especially being able to work with LiveData, e.t.c

It's not totally crazy to convert to and from Apollo's generated objects and Room compatible objects. A bit of work. We're doing it now - when we have time we might try to improve it by autogenerating the converters, maybe, HMU if anyone else has gone this route

Even if Room annotations are generated on the model classes, they won't be available on next round for annotation processing and room won't pick them, if I'm right. So there'll be a need of compilation twice

So, the model classes may not be possible to generate. Hand made classes are error-prone and boilerplate, and a lot of duplication. This is an interesting problem.

https://developer.android.com/training/data-storage/room/defining-data#autovalue might help. Room now allows you to use something like autovalue, maybe we can leverage same code path

Hmm, AutoValue factory will work. But this will mean the integration will only be possible for AutoValue Java users and they still will have to write the entities by hand, which is a lot of error-prone duplicating boilerplate. Also, Kotlin data classes won't work. But at least it is better than something, still not something other people will be able to adopt

One benefit I see from above discussion is to support LiveData. That can be done without room integration. What else does Room support provide? It's not clear to me.

@tasomaniac Room would be only a _sugar syntax_ for writing SQLite databases, something you could achieve SQLDelight or simple old brute force coding.

We have some use case scenarios where a lot of data must be stored to later be synced to the server. Some typical locations without immediate internet sync:

  • Farms, forest, fields, etc
  • Hospitals (sometimes you can connect with a local server)
  • Countries with really expensive mobile internet services (people have to turn the connection on/off constantly in order to not spend a lot of money)

It quite common you find situations where users have more than 1M records at a device, so I would know if simply caching them as a JSON string would perform well.

I was thinking about refactoring StorIO to use Room, taking advantage of its existing plugins and annotations.

After seeing how Apollo Android handles the offline/online sync so elegantly (behaving like a repository pattern), I am studying how we could add/modify its plugins in order to take advantage of Room libraries.

Does it make sense, people?

@sav007 has there been any development in this direction ?. We are using apollo graphql in our app and were planning to add room as well.

@jpventura what would be the actually benefit of using Room APIs within Apollo? 2 biggest benefits of Room are already handled by Apollo: being able to create db easily and having an object mapping.

I would be really happy to shape the discussion to see what features that are missing in Apollo? Then, we can go with an approach that will help Apollo and it's users.

Otherwise it sounds like it is an extra effort with not much benefit.

We are moving towards Kotlin Multiplatform and Room does not support that unfortunately. Closing this for now.

Was this page helpful?
0 / 5 - 0 ratings