2

我是 GraphQL 的新手,所以我想在开始我自己的项目之前测试一些东西。作为测试数据库,我在我的应用程序中使用Prisma测试数据库和服务以及Apollo Android作为库。我几乎完成了queryand mutation。作为下一个我想用subscription. 所以,我的 graphql 订阅看起来像:

subscription observer {
  post {
    mutation
    node {
      id
      title
      text
      isPublished
    }
  }
}

由于 Apollo Android 库会根据我的 graphql 代码生成一些类,因此我尝试observer像这样使用订阅:

Interceptor interceptor = chain -> chain.proceed(chain.request());

OkHttpClient ohc = new OkHttpClient.Builder().addInterceptor(interceptor).build();

ApolloClient mApolloClient = ApolloClient.builder().serverUrl(ENDPOINT).okHttpClient(ohc).build();
mApolloClient.subscribe(ObserverSubscription.builder().build()).execute(new ApolloSubscriptionCall.Callback<ObserverSubscription.Data>() {
    @Override
    public void onResponse(@NotNull Response<ObserverSubscription.Data> response) {
        // do work here
    }

    @Override
    public void onFailure(@NotNull ApolloException e) {
        // catch exception
    }

    @Override
    public void onCompleted() {
        // some other stuff goes here
    }
});

执行以下代码时抛出异常:

java.lang.IllegalStateException:未配置订阅管理器

此消息来自这里,它与this直接相关。

我的问题是有什么方法可以在 Android 应用程序中使用 apollo-android 订阅?

4

1 回答 1

3

首先,很抱歉迟到的答案,我只是遇到了同样的问题,并且使用了很多网站的信息,我成功订阅了。

当你配置你的 ApolloClient 时,你需要定义一些额外的参数:

首先是规范化缓存,对于这个我使用默认配置:

 NormalizedCacheFactory normalizedCacheFactory(){
        return new LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(10 * 1024).build());
    }

和 cacheKeyResolver:

CacheKeyResolver cacheKeyResolver(){
        return new CacheKeyResolver() {
            @Nonnull
            @Override
            public CacheKey fromFieldRecordSet(@Nonnull ResponseField field, @Nonnull Map<String, Object> recordSet) {
                if (recordSet.containsKey("id")) {
                    String id = (String) recordSet.get("id");
                    return CacheKey.from(id);
                }
                return CacheKey.NO_KEY;
            }

            @Nonnull @Override
            public CacheKey fromFieldArguments(@Nonnull ResponseField field, @Nonnull Operation.Variables variables) {
                return CacheKey.NO_KEY;
            }
        };
    }

在 cacheKeyResolver 上,您需要指定如何检测对象中的 ID,在我的情况下,所有对象的名称开头都包含“id”。您可以使用相同的结构添加更多参数。

这两个配置都在 ApolloClient 构建器中:

Map<String, Object> connectionParams = new HashMap<>();
        return ApolloClient.builder()
                .serverUrl(urlBaseDeDatos)
                .normalizedCache(normalizedCacheFactory(),cacheKeyResolver())
                .okHttpClient(okHttpClient())
                .subscriptionConnectionParams(connectionParams)
                .subscriptionTransportFactory(new WebSocketSubscriptionTransport.Factory(urlBaseDeDatos, okHttpClient()))
                .build();

最后两个是重要的,因为它们控制您的订阅(或者我认为它们控制),一旦我定义了这两个,我就可以订阅。我的 connectionParams 是空的,因为我没有使用身份验证令牌或类似的东西。

现在,对于订阅:

private Flowable<Response<TaskStatusChangedSubscription.Data>> subscription(){
        apolloClient.clearNormalizedCache();
        return Rx2Apollo.from(apolloClient.subscribe(TaskStatusChangedSubscription
                .builder()
                .build()));
    }

只是使用 Apollo.subscribe 方法和来自 RxJava 的一些帮助的普通流,并在同一个函数或另一个函数(如一次性)上执行 .subscribe()。

最后(很抱歉之前的所有解释,但它可以帮助其他人),如果你将你的 apollo builder 更改为这样,你的问题应该得到解决:

Map<String, Object> connectionParams = new HashMap<>();
ApolloClient mApolloClient = ApolloClient.builder().serverUrl(ENDPOINT).okHttpClient(ohc).subscriptionConnectionParams(connectionParams)
                .subscriptionTransportFactory(new WebSocketSubscriptionTransport.Factory(ENDPOINT, okHttpClient()))
                .build();
于 2019-02-22T18:25:18.153 回答