Android 改造中的动态路径

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23279006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:58:41  来源:igfitidea点击:

Dynamic Paths in Retrofit

androidresthttprequestretrofit

提问by f2prateek

I'm trying to access a resource with like http://192.168.1.64:5050/api/{api_key}/updater.info.

我正在尝试使用 like 访问资源http://192.168.1.64:5050/api/{api_key}/updater.info

How would I dynamically set the api_keyparameter? I've tried using a RequestInterceptorwithout success where the base url is http://192.168.1.64:5050/api/{api_key}.

我将如何动态设置api_key参数?我试过RequestInterceptor在基本 url 是http://192.168.1.64:5050/api/{api_key}.

@Override
public void intercept(RequestFacade request) {
    request.addPathParam("api_key", apiKey);
}

Are there any other alternatives?

还有其他选择吗?

采纳答案by Jake Wharton

Path replacement does not happen inside the base URL of the API endpoint, only the relative URL string on the method. I'm going to assume you don't want to prefix the relative URLs on every one of your interface method declarations.

路径替换不会发生在 API 端点的基本 URL 内,只会发生在方法上的相对 URL 字符串中。我将假设您不想在每个接口方法声明中添加相对 URL 的前缀。

While poorly worded, the javadoc of Endpointstates:

虽然措辞不佳,但 javadocEndpoint指出:

Callers should always consult the instance for the latest values rather than caching the returned values.

调用者应始终咨询实例以获取最新值,而不是缓存返回值。

This means that for every request the Endpointinstance will be consulted for the value of the base URL.

这意味着对于每个请求,Endpoint实例都会被查询基本 URL 的值。

You can supply a custom Endpointimplementation on which you can change the API key value:

您可以提供Endpoint可以更改 API 密钥值的自定义实现:

public final class FooEndpoint implements Endpoint {
  private static final String BASE = "http://192.168.1.64:5050/api/";

  private String url;

  public void setApiKey(String apiKey) {
    url = BASE + apiKey;
  }

  @Override public String getName() {
    return "default";
  }

  @Override public String getUrl() {
    if (url == null) throw new IllegalStateException("API key not set.");
    return url;
  }
}

回答by cgr

Use this:

用这个:

@PUT("/path1/path2/{userId}")
void getSomething(
        @Path("userId") String userId
);

and you call the method like this:

你像这样调用方法:

String userId = "1234";
service.getSomething(userId);

回答by Jessy Conroy

If the path parameter is not in the same position in the url for each request, for example, http://endpoint/blah/{apiKey}and http://endpoint/blah/blah/{apiKey}/blah, you could do the following.

如果每个请求的路径参数在 url 中的位置不同,例如 http://endpoint/blah/{apiKey}http://endpoint/blah/blah/{apiKey}/blah,您可以执行以下操作。

In your APIService Interface

在您的 APIService 接口中

    @GET(/blah/{apiKey})
    void getFoo(Callback<Object> callback);

    @GET(/blah/blah/{apiKey}/blah)
    void getFooBlah(Callback<Object> callback);

Then in your ApiClient Class create a RequestInterceptor

然后在你的 ApiClient 类中创建一个 RequestInterceptor

private static APIService sAuthorizedApiService;
private static Gson gson;

static {
    gson = new GsonBuilder().setPrettyPrinting()
            .create();
}


public static synchronized APIService getApiClient(final Context context) {
    if (sAuthorizedApiService == null) {
        RequestInterceptor requestInterceptor = new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
                request.addPathParam("apiKey", DataProvider.getInstance(context).getApiKey();
            }
        };

        RestAdapter restAdapter = new RestAdapter.Builder().setLogLevel(RestAdapter.LogLevel.FULL)
                .setClient(new OkClient(new OkHttpClient()))
                .setEndpoint("http://endpoint")
                .setRequestInterceptor(requestInterceptor)
                .setConverter(new GsonConverter(gson))
                .build();
        sAuthorizedApiService = restAdapter.create(GMAuthorizedApiService.class);
    }
    return sAuthorizedApiService;
}