我在Android上尝试使用GitHub GraphQL API v4

Apollo GraphQL 客户端适用于安卓设备

Apollo-Android是一个符合GraphQL标准的客户端,它可以根据标准的GraphQL查询生成Java模型。

毋需开场白,直接开始。它会从GraphQL生成Java代码。通过使用这个库,我将介绍如何使用GitHub API v4的步骤。

开始之前

创建一个合适的Android项目,并导入所需的权限和库。

<uses-permission android:name="android.permission.INTERNET" />

在项目的build.gradle文件的dependencies中添加以下内容。

dependencies {
    ...

    classpath 'com.apollographql.apollo:gradle-plugin:0.4.0'
}

在模块的 build.gradle 中添加以下内容(请确保 apollo 插件在 android 插件之下)。

apply plugin: 'com.android.application'
apply plugin: 'com.apollographql.android'

还增加了一个库,使得可以选择使用 RxJava2。

dependencies {
    ...

    compile "io.reactivex.rxjava2:rxjava:2.1.1"
    compile "io.reactivex.rxjava2:rxandroid:2.0.1"
    compile "com.apollographql.apollo:apollo-rx2-support:0.4.0"
}

阿波羅利用的基本步驟

    1. 安装apollo-codegen

 

    1. 下载schema.json

 

    1. 使用GraphQL创建查询

 

    1. 生成Java代码

 

    1. 使用生成的代码

使用OkHttp进行身份验证
创建ApolloClient
调用方法

安装apollo-codegen

安装将GraphQL生成为Java的工具。此步骤仅在第一次需要执行。

npm install -g apollo-codegen

请务必使用”-g”命令进行安装。如果不进行全局安装,Android 项目将无法访问,因此无法生成代码。

如果没有安装npm,请安装Node.js。

2. 下载 schema.json 文件

在Apollo中生成代码需要包含详细的API描述的schema.json和定义实际查询的~.graphql文件。首先从GitHub下载schema.json。访问GitHub API的终端节点需要访问令牌,所以请按照以下步骤先获取访问令牌。

点击GitHub上的个人资料图片打开设置。选择左下角的个人访问令牌,会出现”生成新令牌”按钮,通过点击该按钮可以生成访问令牌。在这个示例中,使用的范围是用户和存储库,将用于获取用户数据和更新存储库的问题。

※这是限定个人使用的令牌,请注意使用方式。如果您在应用程序中实际使用,可通过OAuth轻松获取访问令牌。

github_settings.png

当准备好访问令牌后,使用apollo-codegen下载schema.json。

apollo-codegen download-schema https://api.github.com/graphql --output schema.json --header "Authorization: Bearer <access-token>"

1MB 大小的 schema.json 文件会下载到执行命令的目录中(稍后将用于生成 Java 代码)。

3. 利用 GraphQL 创建查询

我现在要创建一个简单的查询,只是提取用户信息。这个查询是基于打开 GitHub 的 GraphiQL 时出现的示例查询,并添加了一些项目。Apollo不支持省略操作和查询名称的GraphQL格式,因此需要提供操作名称和适当的查询名称。由于这是一个查询操作,所以需要使用`query`关键字,并给它命名为`Viewer`。生成的代码的类名将是查询名称+操作名称,所以将是`ViewerQuery`。

query Viewer {
  viewer {
    login
    bio
    avatarUrl
    company
    location
  }
}

为了确认一下,可以在 GraphiQL 中尝试执行查询,结果如下。

fig2.png

请将此查询保存在名为 API.graphql 的文件中,以普通文本格式保存(文件名中的 API 部分可以是任何名称,但必须将扩展名设置为 .graphql)。

4. 生成代碼

从上一步创建的schema.json和API.graphql中生成Java代码。在预先创建的项目的src/main目录下创建一个名为graphql的文件夹。在其中创建与应用程序包名称对应的目录结构,并将schema.json和API.graphql放置其中。生成的类将以此目录结构为基础生成包名。在这里,我们将在应用程序的根包中添加一个名为api的包结构。将Android Studio的视图切换为Project Files并展开,就会呈现如下的样子。

dirs.png

在这个状态下进行应用程序的构建,Apollo插件会为您生成代码。生成的代码位于build/generated目录下。

使用生成的代码

您可以通过ApolloClient调用生成的代码。与下载schema.json时相同,ApolloClient需要提供身份验证处理,因为它需要一个bearer token。由于ApolloClient可以将OkHttp用作HTTP客户端,因此您可以使用OkHttp的Authenticator(或Interceptor)来进行身份验证。

OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .authenticator(new Authenticator() {
            @Override
            public Request authenticate(Route route, okhttp3.Response response) throws IOException {
                return response.request().newBuilder()
                        .addHeader("Authorization", "Bearer <access-token>")
                        .build();
            }
        }).build();

创建 ApolloClient。将先前创建的 okHttpClient 和 API 的终点传递给它。

ApolloClient apolloClient = ApolloClient.builder()
        .okHttpClient(okHttpClient)
        .serverUrl("https://api.github.com/graphql")
        .build();

用之前生成的代码向 GitHub 发送请求。

Rx2Apollo.from(apolloClient.query(new ViewerQuery()).watcher())
        .subscribeOn(Schedulers.io())
        .subscribe(new DisposableObserver<Response<ViewerQuery.Data>>() {
            @Override
            public void onNext(Response<ViewerQuery.Data> dataResponse) {
                android.util.Log.d("graphql", "" + dataResponse.data());
            }

            @Override
            public void onError(Throwable e) {
                android.util.Log.d("graphql", "" + e);
            }

            @Override
            public void onComplete() {
                // no-op
            }
        });

当成功时,会返回类似以下响应(实际响应为JSON文本,它尚未包装在生成的代码之前)。

D/graphql: Data{viewer=Viewer{__typename=User, login=mightyfrog, name=, company=, avatarUrl=https://avatars0.githubusercontent.com/u/208494?v=4, bio=Android developer @DeNA, createdAt=2010-02-22T16:04:03Z}}

试着创建一个接受参数的查询

我试图通过指定用户名来获取用户数据。查询的形式如下。

{
  user(login: "mightyfrog") {
    id
    login
    bio
    avatarUrl
    company
    createdAt
  }
}

将这个转换为变量可用的格式。

query User($login: String!) {
  user(login: $login) {
    id
    login
    bio
    avatarUrl
    company
    createdAt
  }
}

在 GraphiQL 中进行测试。变量的值会写在 QUERY VARIABLES 中发送。

{
  "login": "mightyfrog"
}
fig3.png

将经过修改以使用变量的查询添加到之前创建的 API.graphql 中。

query Viewer {
  viewer {
    login
    name
    company
    avatarUrl
    bio
    createdAt
  }
}

query User($login: String!) {
  user(login: $login) {
    id
    login
    bio
    avatarUrl
    company
    createdAt
  }
}

当项目进行构建时,将生成一个新的UserQuery类,因此我们将尝试使用它。构造函数现在接受参数。

Rx2Apollo.from(apolloClient.query(new UserQuery("mightyfrog")).watcher())
        .subscribeOn(Schedulers.io())
        .subscribe(new DisposableObserver<Response<UserQuery.Data>>() {
            @Override
            public void onNext(Response<UserQuery.Data> dataResponse) {
                android.util.Log.d("graphql", "" + dataResponse.data());
            }

            @Override
            public void onError(Throwable e) {
                android.util.Log.d("graphql", "" + e);
            }

            @Override
            public void onComplete() {
                // no-op
            }
        });

会返回这样的结果。

D/graphql: Data{user=User1{__typename=User, id=MDQ6VXNlcjIwODQ5NA==, login=mightyfrog, bio=Android developer @DeNA, avatarUrl=https://avatars0.githubusercontent.com/u/208494?v=4, company=, createdAt=2010-02-22T16:04:03Z}}

试着更新数据

我們將在 GitHub 上 The Octocat 帳戶的 Hello-World 倉庫的 issue349 上添加表情符號反應。我們將在 API.graphql 中添加以下內容並生成程式碼。

mutation AddReactionToIssue($subjectId: ID!, $content: ReactionContent!) {
  addReaction(input:{subjectId: $subjectId,content: $content}) {
    reaction {
      content
    }
    subject {
      id
    }
  }
}

在GraphiQL中尝试时会是这样的感觉。

fig4.png

使用以下的查询可以获取到问题号,在您自己的代码库中也可以尝试一下。

query FindIssueID {
  repository(owner: "octocat", name: "Hello-World") {
    issue(number: 349) {
      id
    }
  }
}

使用构建生成的代码进行执行。

Rx2Apollo.from(apolloClient.mutate(new AddReactionToIssueMutation("MDU6SXNzdWUyMzEzOTE1NTE=", ReactionContent.HEART)))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new DisposableObserver<Response<AddReactionToIssueMutation.Data>>() {
            @Override
            public void onNext(Response<AddReactionToIssueMutation.Data> dataResponse) {
                mTextView.setText("" + dataResponse.data());
                android.util.Log.d("graphql", "" + dataResponse.data());
            }

            @Override
            public void onError(Throwable e) {
                android.util.Log.d("graphql", "" + e);
            }

            @Override
            public void onComplete() {
                // no-op
            }
        });

回应如下所示。

D/graphql: Data{addReaction=AddReaction{__typename=AddReactionPayload, reaction=Reaction{__typename=Reaction, content=HEART}, subject=Subject{__typename=Issue, id=MDU6SXNzdWUyMzEzOTE1NTE=}}}

更新也包括 issue349 的反应。

reaction.png

它結束了

Apollo GraphQL Client for Android是一个还只发布了大约三个月的库,可以说处理起来有些麻烦,性能方面也不明确,但可以完成类似这个演示的任务。尽管本次没有使用,但它也支持使用别名、片段和指令等更复杂的查询。还有提供Kotlin插件,并且未来还计划支持Proguard和Auto-Value,使这个库更加值得期待。

如果你已经读到这里,那么你一定对GraphQL本身也产生了兴趣。如果你想了解更多关于GraphQL方面的知识,我推荐你参考GitHub的GraphQL概述和graphql.org的GraphQL简介。

以下是我們原本打算在 shibuya.apk #17 上使用的示範 GraphQL API 伺服器:
https://github.com/mightyfrog/Simple-GraphQL-API-Server

请参考以下资料

请参考提供的参考资料

以下资料可供参考

请参考以下资料选项

请参考下列资料

    • http://graphql.org/

 

    • https://developer.github.com/v4/

 

    • https://github.com/apollographql

 

    • https://github.com/chentsulin/awesome-graphql

 

    • https://code.facebook.com/posts/1691455094417024

 

    • https://facebook.github.io/react/blog/2015/05/01/graphql-introduction.html

 

    https://githubengineering.com/the-github-graphql-api/