Git Product home page Git Product logo

apollo-android's Introduction

Apollo GraphQL Client for Android

GitHub license Get on Slack Build status

Apollo-Android is a GraphQL compliant client that generates Java models from standard GraphQL queries. These models give you a typesafe API to work with GraphQL servers. Apollo will help you keep your GraphQL query statements together, organized, and easy to access from Java. Change a query and recompile your project - Apollo code gen will rebuild your data model. Code generation also allows Apollo to read and unmarshal responses from the network without the need of any reflection (see example generated code below). Future versions of Apollo-Android will also work with AutoValue and other value object generators.

Usage

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'com.apollographql.android:gradle-plugin:$CURRENT_APOLLO_VERSION'
  }
}

apply plugin: 'com.apollographql.android'

To use Apollo, put your GraphQL queries in a .graphql file, like src/main/graphql/com/example/DroidDetails.grapqhl. There is nothing special about this query, it can be shared with other GraphQL clients as well

query DroidDetails {
  species(id: "c3BlY2llczoy") {
    id
    name
    classification
  }
}

From this, Apollo will generate a DroidDetails Java class with nested classes for reading from the network response.

@Generated("Apollo GraphQL")
public final class DroidDetails implements Query<Operation.Variables> {
  public static final String OPERATION_DEFINITION = "query DroidDetails {\n"
      + "  species(id: \"c3BlY2llczoy\") {\n"
      + "    id\n"
      + "    name\n"
      + "    classification\n"
      + "  }\n"
      + "}";

  public static final String QUERY_DOCUMENT = OPERATION_DEFINITION;

  private final Operation.Variables variables;

  public DroidDetails() {
    this.variables = Operation.EMPTY_VARIABLES;
  }

  @Override
  public String queryDocument() {
    return QUERY_DOCUMENT;
  }

  @Override
  public Operation.Variables variables() {
    return variables;
  }

  public static class Data implements Operation.Data {
    private static final ResponseFieldMapper<Data> MAPPER = new ResponseFieldMapper<Data>() {
      private final Field[] FIELDS = {
        Field.forObject("species", "species", null, true, new Field.ObjectReader<Species>() {
          @Override public Species read(final ResponseReader reader) throws IOException {
            return new Species(reader);
          }
        })
      };

      @Override
      public void map(final ResponseReader reader, final Data instance) throws IOException {
        reader.read(new ResponseReader.ValueHandler() {
          @Override
          public void handle(final int fieldIndex, final Object value) throws IOException {
            switch (fieldIndex) {
              case 0: {
                instance.species = (Species) value;
                break;
              }
            }
          }
        }, FIELDS);
      }
    };
    
    private @Nullable Species species;

    public Data(ResponseReader reader) throws IOException {
      MAPPER.map(reader, this);
    }

    public Data(@Nullable Species species) {
      this.species = species;
    }

    public @Nullable Species species() {
      return this.species;
    }

    public static class Species {
      private static final ResponseFieldMapper<Species> MAPPER = new ResponseFieldMapper<Species>() {
        private final Field[] FIELDS = {
          Field.forString("id", "id", null, false),
          Field.forString("name", "name", null, true),
          Field.forString("classification", "classification", null, true)
        };

        @Override
        public void map(final ResponseReader reader, final Species instance) throws IOException {
          reader.read(new ResponseReader.ValueHandler() {
            @Override
            public void handle(final int fieldIndex, final Object value) throws IOException {
              switch (fieldIndex) {
                case 0: {
                  instance.id = (String) value;
                  break;
                }
                case 1: {
                  instance.name = (String) value;
                  break;
                }
                case 2: {
                  instance.classification = (String) value;
                  break;
                }
              }
            }
          }, FIELDS);
        }
      };

      private @Nonnull String id;

      private @Nullable String name;

      private @Nullable String classification;

      public Species(ResponseReader reader) throws IOException {
        MAPPER.map(reader, this);
      }
      
      public @Nonnull String id() {
        return this.id;
      }

      public @Nullable String name() {
        return this.name;
      }

      public @Nullable String classification() {
        return this.classification;
      }
  }
}

Consuming Code

You can use the generated classes with Retrofit to make requests to your GraphQL API. Apollo includes a ApolloConverterFactory which when registered with Retrofit will offer reflection-free response to Java mapping.

interface ApiService {
  @POST("/") Call<Response<DroidDetails.Data>> droidDetails(@Body OperationRequest<Operation.Variables> query);
}
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(okHttpClient)
    .addConverterFactory(new ApolloConverterFactory.Builder().build())
    .addConverterFactory(MoshiConverterFactory.create())
    .build();
ApiService service = retrofit.create(ApiService.class);
service.droidDetails(new OperationRequest<>(new DroidDetails()))
    application.service()
            .droidDetails(new OperationRequest<>(new DroidDetails()))
            .enqueue(new Callback<Response<DroidDetails.Data>>() {
              @Override
              public void onResponse(Call<Response<DroidDetails.Data>> call,
                  retrofit2.Response<Response<DroidDetails.Data>> response) {
                // use the graphql response which is now in Java Models.
              }

              @Override public void onFailure(Call<Response<DroidDetails.Data>> call, Throwable t) {
                // handle error
              }
            });

License

The MIT License (MIT)

Copyright (c) 2016 Meteor Development Group, Inc.

apollo-android's People

Contributors

digitalbuddha avatar felipecsl avatar kassim avatar martijnwalraven avatar martinbonnin avatar marwanad avatar sav007 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.