使用Retrofit v1.9.0添加重复参数

Nir*_*raj 4 android retrofit

有一个类似的问题问在这里,但我的情况有点不同.

我正在尝试提出类似以下的请求:

http://www.example.com/abc?foo=def&foo=ghi&foo=jkl&bar=xyz

我有两个问题让事情变得困难.首先,重复参数("foo"多次设置值)阻止使用QueryMap(我没有选项以不同的方式传递查询字符串中的值,就像数组一样).其次,我正在使用的查询参数是动态的,所以我不能真正使用Query并为它提供给定参数名称的值列表,因为在我发出请求之前我不会知道参数名称.

我试图从升级的代码使用改造的旧版本,但不知何故,它有一个概念QueryList,其采取了ListNameValuePairS IN查询参数传递的名称(及其作为值值),并允许重复的参数.我没有retrofit.http.QueryList在Retrofit的源代码历史记录或网络上看到任何引用,所以我不确定这是否是当时的自定义添加.在任何情况下,我都试图找到在最新版本中复制该功能的最佳方式,所以任何帮助将不胜感激!

Nir*_*raj 18

为了跟进,我能够通过使用QueryMap和一些黑客来解决这个问题.基本上我把我ListNameValuePairs转换成HashMap,在那里我检查我是否已经拥有密钥,如果我这样做,我将相同密钥的新值附加到旧值.所以基本上(键,值)会变成(键,值和键=值2).这样,当构造查询字符串时,我将根据需要使用key = value&key = value2.为了使其工作,我需要自己处理值编码,以便我在值中包含的额外&符号和等号不会被编码.

所以这HashMap是由List这样构造的:

public static HashMap<String, String> getPathMap(List<NameValuePair> params) {
    HashMap<String, String> paramMap = new HashMap<>();
    String paramValue;

    for (NameValuePair paramPair : params) {
        if (!TextUtils.isEmpty(paramPair.getName())) {
            try {
                if (paramMap.containsKey(paramPair.getName())) {
                    // Add the duplicate key and new value onto the previous value
                    // so (key, value) will now look like (key, value&key=value2)
                    // which is a hack to work with Retrofit's QueryMap
                    paramValue = paramMap.get(paramPair.getName());
                    paramValue += "&" + paramPair.getName() + "=" + URLEncoder.encode(String.valueOf(paramPair.getValue()), "UTF-8");
                } else {
                    // This is the first value, so directly map it
                    paramValue = URLEncoder.encode(String.valueOf(paramPair.getValue()), "UTF-8");
                }
                paramMap.put(paramPair.getName(), paramValue);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }

    return paramMap;
}
Run Code Online (Sandbox Code Playgroud)

然后我的请求看起来像这样:

@GET("/api/")
List<Repo> listRepos(@QueryMap(encodeValues=false) Map<String, String> params);
Run Code Online (Sandbox Code Playgroud)

我的服务电话看起来像这样:

// Get the list of params for the service call
ArrayList<NameValuePair> paramList = getParams();

// Convert the list into a map and make the call with it
Map<String, String> params = getPathMap(paramList);
List<Repo> repos = service.listRepos(params);
Run Code Online (Sandbox Code Playgroud)

我最初尝试使用Path手动构建查询字符串的解决方案,但查询字符串中不允许使用替换块,因此我使用了此QueryMap解决方案.希望这可以帮助遇到同样问题的其他人!