首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在安卓系统中使用GraphQl?

如何在安卓系统中使用GraphQl?
EN

Stack Overflow用户
提问于 2017-04-08 09:47:49
回答 4查看 6.8K关注 0票数 4

我需要一个在安卓系统中使用GraphQl的简单例子。

如何在安卓系统中使用GraphQl (教程)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-04-08 10:23:50

为了使用GraphQL (一般情况下),您需要两件事:

1. GraphQL服务器

有几种方法可以让你做到这一点。当然,您可以使用您喜欢的任何服务器端语言简单地使用go和自己实施一项。其他(更快)的方法是利用现有的工具,使用诸如图形up创建-graphql-服务器之类的服务,甚至使用格酷 (免责声明:我为它们工作)来生成图形up API。

2. GraphQL客户端库

虽然这不是绝对必要的,而且您也可以通过简单的HTTP (发送查询和POST请求体中的突变)与GraphQL服务器交互,但是使用现有的工具来完成重复的工作,比如缓存或UI集成,当然是有益的。目前最流行的GraphQL客户机之一是阿波罗,他们也非常积极地开发Android版本。然而,这还没有正式发布。所以,现在您要么必须使用他们现有的开发版本选择使用普通HTTP的前一种方法。

票数 7
EN

Stack Overflow用户

发布于 2017-07-15 20:36:48

下面是一个从客户端查询GraphQl的示例。在本例中,我使用Retrofit 2:

代码语言:javascript
运行
复制
// QueryHelper.java
// This line below is the simple format of Gql query
query = "query{me{name, location, majorOfInterest,profilePhoto{url(size: 400) }}}";

//Post the query using Retrofit2
GqlRetrofitClient.getInstance(getContext()).fetchUserDetails(new GqlQueryRequest(queryUserDetails)).enqueue(new Callback<UserDetails>() {
  @Override
  public void onResponse(Call<UserDetails> call, Response<UserDetails> response) {
     //OnResponse do something();       
     }

  @Override
  public void onFailure(Call<UserDetails> call, Throwable t) {
    Log.d(TAG, "Failed to fetch User details");
    }
    });


//GqlClient.java
public class GqlRetrofitClient {
public static final String BASE_URL = BuildConfig.DOMAIN;
private static GqlRetrofitClient sInstance;
private GqlRetrofitService mGqlRetrofitService;

Gson gson = new GsonBuilder().create();

  private GqlRetrofitClient(final Context context) {
    // Network Interceptor for logging
    HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
    httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .addNetworkInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request().newBuilder()
                            .addHeader("X-User-Token", "AUTH_TOKEN")
                            .addHeader("X-User_Email", "Email")
                            .addHeader("content-type", "application/json")
                            .build();
                    return chain.proceed(request);
                }
            })
            .addInterceptor(httpLoggingInterceptor)
            .build();

    // Retrofit initialization
    final Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(okHttpClient)
            .build();

    mGqlRetrofitService = retrofit.create(GqlRetrofitService.class);
 }

  // Create an instance of GqlRetrofitClient to create retrofit service
  public static GqlRetrofitClient getInstance(Context context){
    if(sInstance == null){
        sInstance = new GqlRetrofitClient(context.getApplicationContext());
    }
    return sInstance;
  }

  // Method call to get User details
  public Call<UserDetails> fetchUserDetails(GqlQueryRequest queryUserDetails){
    return mGqlRetrofitService.getUserDetails(queryUserDetails);
  }
}

//GqlRetrofitService.java
public interface GqlRetrofitService{
  @POST("/api/graph.json")
  Call<UserDetails> getUserDetails(@Body GqlQueryRequest body);
}
票数 4
EN

Stack Overflow用户

发布于 2020-08-28 08:47:22

就我个人而言,我使用Retrofit,我使用了这个链接信用并改变了一些东西。

这是代码:

在“GraphQLConverter.java”文件中:

代码语言:javascript
运行
复制
public class GraphQLConverter extends Converter.Factory {

    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");

    private GraphQueryProcessor graphProcessor;
    private final Gson mGson;

    private GraphQLConverter(Context context) {
        graphProcessor = new GraphQueryProcessor(context);
        mGson = new GsonBuilder()
                .enableComplexMapKeySerialization()
                .setLenient()
                .create();
    }

    public static GraphQLConverter create(Context context) {
        return new GraphQLConverter(context);
    }

    /** Override Converter.Factory Methods **/
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return null;
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        if(type == QueryContainerBuilder.class){
            return new GraphRequestConverter(methodAnnotations);
        } else {
            return null;
        }
    }

    /** RequestConverter Class **/
    private class GraphRequestConverter implements Converter<QueryContainerBuilder, RequestBody> {

        private Annotation[] mAnnotations;

        private GraphRequestConverter(Annotation[] annotations) {
            mAnnotations = annotations;
        }

        @Override
        public RequestBody convert(@NonNull QueryContainerBuilder containerBuilder) {
            QueryContainerBuilder.QueryContainer queryContainer = containerBuilder
                    .setQuery(graphProcessor.getQuery(mAnnotations))
                    .build();
            return RequestBody.create(MEDIA_TYPE, mGson.toJson(queryContainer).getBytes());
        }

    }
}

在“GraphQuery.java”文件中:

代码语言:javascript
运行
复制
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GraphQuery {

    String value() default "";

}

在“GraphQueryProcessor.java”文件中:

代码语言:javascript
运行
复制
class GraphQueryProcessor {

    private static final String TAG = GraphQueryProcessor.class.getSimpleName();
    // GraphQl Constants
    private static final String EXT_GRAPHQL = ".graphql";
    private static final String ROOT_FOLDER_GRAPHQL = "graphql";

    private final Map<String, String> mGraphQueries;
    private Context mContext;

    GraphQueryProcessor(Context context) {
        mGraphQueries = new WeakHashMap<>();
        mContext = context;
        populateGraphQueries(ROOT_FOLDER_GRAPHQL);
    }

    /** Package-Private Methods **/
    String getQuery(Annotation[] annotations) {
        if(mGraphQueries == null || mGraphQueries.isEmpty()){
            populateGraphQueries(ROOT_FOLDER_GRAPHQL);
        }

        GraphQuery graphQuery = null;
        for (Annotation annotation : annotations) {
            if (annotation instanceof GraphQuery) {
                graphQuery = (GraphQuery) annotation;
                break;
            }
        }

        if (graphQuery != null) {
            String fileName = String.format("%s%s", graphQuery.value(), EXT_GRAPHQL);
            if (mGraphQueries != null && mGraphQueries.containsKey(fileName)) {
                return mGraphQueries.get(fileName);
            }
        }
        return null;
    }

    /** Private Methods **/
    private void populateGraphQueries(@NonNull String path) {
        try {
            String[] paths = mContext.getAssets().list(path);
            if (paths != null && paths.length > 0x0) {
                for (String item : paths) {
                    String absolute = path + "/" + item;
                    if (!item.endsWith(EXT_GRAPHQL)) {
                        populateGraphQueries(absolute);
                    } else {
                        mGraphQueries.put(item, getFileContents(mContext.getAssets().open(absolute)));
                    }
                }
            }
        } catch (IOException ioE) {
            BaseEnvironment.onExceptionLevelLow(TAG, ioE);
        }
    }

    private String getFileContents(InputStream inputStream) {
        StringBuilder queryBuffer = new StringBuilder();
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            for (String line; (line = bufferedReader.readLine()) != null; )
                queryBuffer.append(line);
            inputStreamReader.close();
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return queryBuffer.toString();
    }

}

在“QueryContainerBuilder.java”文件中:

代码语言:javascript
运行
复制
public class QueryContainerBuilder {

    // Mask Types
    private static final byte MASK_REPLACE_QUERY_ARGUMENTS =    0b1;     // Invece di inviare il json con le variabili va a inserirle nella query i valori sostituendo i tipi degli argomenti.
    private static final byte MASK_REPLACE_EXPLICIT_QUOTES =    MASK_REPLACE_QUERY_ARGUMENTS << 0b1;     // Alle stringhe non vengono automaticamente messe le virgolette ma devono essere aggiunte nei valori passati per le variabili.
    private static final byte MASK_REPLACE_WITH_PLACEHOLDERS =  MASK_REPLACE_EXPLICIT_QUOTES << 0b1;     // Va a sostituire i placeholders "<key_var_name>" presenti nella query con i valori delle variabili.

    private QueryContainer mQueryContainer;
    private byte mMask;

    public QueryContainerBuilder() {
        mQueryContainer = new QueryContainer();
    }

    /** Setter Methods **/
    public QueryContainerBuilder setQuery(String query) {
        mQueryContainer.setQuery(query);
        return this;
    }

    public QueryContainerBuilder setReplaceQueryArguments(){
        mMask = MASK_REPLACE_QUERY_ARGUMENTS;
        return this;
    }

    public QueryContainerBuilder setReplaceExplicitQuotes(){
        mMask =  MASK_REPLACE_QUERY_ARGUMENTS | MASK_REPLACE_EXPLICIT_QUOTES;
        return this;
    }

    public QueryContainerBuilder setReplaceWithPlaceholders(){
        mMask = MASK_REPLACE_QUERY_ARGUMENTS | MASK_REPLACE_WITH_PLACEHOLDERS;
        return this;
    }

    /** Public Methods **/
    public QueryContainerBuilder putVariable(String key, Object value) {
        mQueryContainer.putVariable(key, value);
        return this;
    }

    public boolean containsVariable(String key) {
        return mQueryContainer.containsVariable(key);
    }

    /** Builder Methods **/
    public QueryContainer build() {
        if((mMask & MASK_REPLACE_QUERY_ARGUMENTS) != 0x0){
            if((mMask & MASK_REPLACE_WITH_PLACEHOLDERS) != 0x0){
                mQueryContainer.replaceVariablesPlaceholdersInQuery();
            } else {
                mQueryContainer.replaceVariablesInQuery(mQueryContainer.mVariables, 0x0);
            }
            mQueryContainer.mVariables = null;
        }
        return mQueryContainer;
    }

    /** Public Static Classes **/
    public class QueryContainer {

        @SerializedName("variables")
        private LinkedHashMap<String, Object> mVariables;
        @SerializedName("query")
        private String mQuery;

        QueryContainer() {
            mVariables = new LinkedHashMap<>();
        }

        /** Private Methods **/
        private void setQuery(String query) {
            mQuery = query;
        }

        private void putVariable(String key, Object value) {
            mVariables.put(key, value);
        }

        private boolean containsVariable(String key) {
            return mVariables != null && mVariables.containsKey(key);
        }

        private void replaceVariablesInQuery(LinkedHashMap<String, Object> map, int index){
            if(!TextUtils.isEmpty(mQuery) && map.size() > 0x0){
                List<String> keys = new ArrayList<>(map.keySet());
                for(String key : keys){
                    Object value = map.get(key);
                    if(value instanceof LinkedHashMap){
                        replaceVariablesInQuery((LinkedHashMap<String, Object>) value, index);
                    } else {
                        int i = mQuery.indexOf(key + ":", index) + key.length() + 0x1;
                        int z;
                        if(keys.indexOf(key) < keys.size() - 0x1){
                            z = mQuery.indexOf(",", i);
                        } else {
                            z = mQuery.indexOf(")", i);
                            int x = mQuery.substring(i, z).indexOf('}');
                            if(x != -0x1){
                                if(mQuery.substring(i, i + 0x4).contains("{")){
                                    x++;
                                }
                                z -= ((z - i) - x);
                            }
                        }

                        String replace;
                        if((mMask & MASK_REPLACE_EXPLICIT_QUOTES) != 0x0){
                            replace = String.valueOf(value);
                        } else {
                            replace = value instanceof String ?
                                    "\"" + value.toString() + "\"" : String.valueOf(value);
                        }
                        String sub = mQuery.substring(i, z)
                                .replaceAll("[\\\\]?\\[", "\\\\\\[").replaceAll("[\\\\]?\\]", "\\\\\\]")
                                .replaceAll("[\\\\]?\\{", "\\\\\\{").replaceAll("[\\\\]?\\}", "\\\\\\}");
                        mQuery = mQuery.replaceFirst(sub.contains("{}") ? sub.replace("{}", "").trim() : sub.trim(), replace);
                        index = z + 0x1;
                    }
                }
            }
        }

        private void replaceVariablesPlaceholdersInQuery(){
            if(!TextUtils.isEmpty(mQuery) && mVariables.size() > 0x0){
                for(String key : mVariables.keySet()){
                    mQuery = mQuery.replaceFirst("\\<" + key + "\\>", mVariables.get(key) != null ? mVariables.get(key).toString() : "null");
                }
                mVariables = null;
            }
        }

    }

}

将查询放在查询文件扩展名为".graphql“的”资产“文件夹中的"graphql”目录中。您可以通过更改"EXT_GRAPHQL“或"ROOT_FOLDER_GRAPHQL”常量在"GraphQueryProcessor"中更改扩展名或文件夹。您可以将这些格式用于查询:

代码语言:javascript
运行
复制
query {
    myQuery(param1: <myParam1>) {
        ....
    }
}

如果您使用这种格式,则需要在您的QueryContainerBuilder中使用QueryContainerBuilder。此外,您还需要作为HashMap键传递没有"<...>“的占位符的名称,因此在本例中是"myParam1”。

其他格式只是常见的GraphQL查询,如:

代码语言:javascript
运行
复制
query ($p1: String!) {
    muQuery(p1: $id) {
        ...
    }
}

使用这种格式,您可以使用"MASK_REPLACE_QUERY_ARGUMENTS"普通QueryContainerBuilder行为(没有应用掩码,因此它将传递和生成“变量”json对象。)或将删除"$id“并放置值的。

当您init时,添加"GraphQLConverter"。让关注"ConvertFactories“顺序!您可以放置更多的ConvertFactory,但是它们使用输入,所以在本例中,如果您将"Gson”放在"GraphQL“之前,"GsonConverted”将使用输入数据:

代码语言:javascript
运行
复制
new Retrofit.Builder()
                .baseUrl(mBaseUrl)
                .addConverterFactory(GraphQLConverter.create(context))
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(getBaseHttpClient(interceptor))
                .build();

在您的Retrofit

代码语言:javascript
运行
复制
@POST(AppConstants.SERVICE_GQL)
@GraphQuery(AppConstants.MY_GRAPHQL_QUERY_FILENAME)
fun callMyGraphQlQuery(@Body query: QueryContainerBuilder): Call<MyGraphQlResponse>

调用示例

代码语言:javascript
运行
复制
val query = QueryContainerBuilder()
                .putVariable("myParam1", myValue)
                .setReplaceWithPlaceholders()
            createService(API::class.java).callMyGraphQlQuery(query)

val query = QueryContainerBuilder()
            .putVariable("p1", myValue)
            .setReplaceQueryArguments()
        createService(API::class.java).callMyGraphQlQuery(query)


val query = QueryContainerBuilder()
            .putVariable("p1", myValue)
        createService(API::class.java).callMyGraphQlQuery(query)

Idk如果"MASK_REPLACE_QUERY_ARGUMENTS“是正确的,我只使用它2/3次,然后后端被更改并写得更好。

我使用这些情况(掩码)来处理查询,因为我调用的后端有3种查询。只需在"QueryContainerBuilder“中添加另一个掩码和代码,就可以添加其他查询处理行为。

如果有人使用这段代码并使它变得更好,请给我写这些更改,这样我也会在我的库中修改代码。

谢谢你,祝你有一个美好的编码和一天:D

再见!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43292529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档