web-dev-qa-db-ja.com

Retrofitで絶対URLを使用する

[〜#〜] hal [〜#〜] 使用しているAPIがあり、多くの場合、取得したURLに(さまざまなメソッドで)リクエストを送信する必要がありますAPI。つまり、レトロフィットAPIインターフェースでURLのパスをハードコーディングしたくないのですが、必要なのは、レトロフィットを使用してそのURLに単純なリクエストを送信することだけです。私は現在Volleyを使用しており、この目的でOkHttpを使用できることは知っていますが、Retrofitでそのようなことを行うための優れた方法があるかどうか疑問に思いました。

6
Kayvan N

最近、Squareは Retrofit v2.0.0 BETA をリリースし、動的URLのサポートが組み込まれています。ライブラリはベータ版ですが、 Jake Wharton がDroidCon NYC 2015で教えてくれたことに基づいて、すべてのAPIは安定しており、変更されません。私は個人的にそれを私の作品に追加しているので、それはあなた次第です。

アップグレードを行う場合は、次のリンクが役立ちます。
JakeWhartonプレゼンテーション@DroidCon NYC 2015
変更に関する非常に優れたガイド

単純なWordでは、パスなしでapiアノテーション(@GETや@POSTなど)を使用できるようになりました。次に、メソッドが呼び出すために使用するapiメソッドに@URLを渡します。

----------------レトロフィット1.x

私はこれを行うための良い方法を考え出し、それを共有したいと思います。

秘訣は、RestAdapterの作成時にエンドポイントとして動的URLを使用し、APIインターフェイスに空のパスを設定することです。

これが私がそれをした方法です:

public RestAdapter getHostAdapter(String baseHost){
    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint(baseHost)
            .setRequestInterceptor(requestInterceptor)
            .build();

    return restAdapter;
}

このメソッドを使用してrestAdapterをビルドすると、インターフェイスに次のようになります。
(URLにクエリパラメータが追加されている場合、これは機能しません。その場合の解決策については、次の回答を参照してください)

public interface General {
    @GET("/")
    void getSomething(Callback<SomeObject> callback);
}

そして最後に次のようにそれらを使用します:

getHostAdapter("YOUR_DYNAMIC_URL").create(General.class)
    .getSomething(new Callback<SomeObject>(){
        ...
    })

それが役に立てば幸い。

23
Kayvan N

URLにもパスが必要なので、次のようにしました。

    @GET("/{path}")
void getMatcherUrl(@Path(value = "path", encode = false) String path, @QueryMap Map<String, String> queryMap, RestCallback<MatcherResponse> matcherResponse);

/**
     * Need to create a custom method because i need to pass a absolute url to the retrofit client
     *
     * @param urlString
     * @param matcherResponse
     */
    public void getMatcherUrl(@NonNull String urlString, @NonNull RestCallback<MatcherResponse> matcherResponse) {
        Uri uri = Uri.parse(urlString);
        Set<String> queryParameterNames = uri.getQueryParameterNames();
        String Host = uri.getHost();
        String path = (uri.getPath().startsWith("/")) ? uri.getPath().substring(1) : uri.getPath();
        HashMap<String, String> queryMap = new HashMap<>();
        Iterator<String> iterator = queryParameterNames.iterator();

        while (iterator.hasNext()) {
            String queryName = iterator.next();
            String queryParameter = uri.getQueryParameter(queryName);
            queryMap.put(queryName, queryParameter);
        }

        getApiCoreService(Host)
                .getMatcherUrl(path, queryMap, matcherResponse);
    }

    public ApiCoreService getApiCoreService(String Host) {
        if (StringUtils.isEmpty(Host))
            this.endpoint = new RestEndpoint(RemoteConfigurationManager.getInstance().getApiCore(), "ApiCore");
        else
            this.endpoint = new RestEndpoint(Host, "ApiCore");
        return apiCoreService;
    }
3
garydossantos

URLにクエリパラメータが含まれている場合、ベースURLの末尾に「/」が追加されるため、上記のソリューションは機能しません。たとえば、URLが

https://www.google.com/?q=test

次に、上記のソリューションはリクエストをに送信しようとします

https://www.google.com/?q=test/

モールフォーマットのため失敗します。

私たちにできることは、もう1つのステップとURLの解析です。解析とは、すべてのURLパラメータを取り出して、QueryMapで送信することを意味します。

方法は次のとおりです。

インターフェースを少し変更して、上記と同じ構造にする必要があります

public interface General {
    @GET("/")
    void getSomething(@QueryMap Map<String,String> queryMap, Callback<SomeObject> callback);
}

上記のインターフェースにQueryMapを追加したところ、次のパーサーメソッドを使用できるようになりました。

public static void getSomething(@NonNull String urlString, @NonNull Callback<SomeObject> callback){
    Uri uri = Uri.parse(urlString);
    Set<String> queryParameterNames = uri.getQueryParameterNames();
    String Host = uri.getHost();
    HashMap<String,String> queryMap = new HashMap<>();
    Iterator<String> iterator = queryParameterNames.iterator();

    while(iterator.hasNext()){
        String queryName = iterator.next();
        String queryParameter = uri.getQueryParameter(queryName);
        queryMap.put(queryName, queryParameter);
    }

    getHostAdapter(Host)
        .create(General.class)
        .getSomething(queryMap, callback);
}

これで、このメソッドを次のように呼び出すことができます。

getSomething("https://www.google.com/?q=test");

コーディングをお楽しみください。

注:QueryMapRetrofit v1.4. に追加されました

3
Kayvan N

上記の2つの答えに加えて、Queryparamを利用して絶対URLを起動する作業クラスを次に示します。

public class VideoClient {

private static final String TAG = "VideoCLient";
private final RestAdapter restAdapter;
private General apiService;
private String hostName;
private LinkedHashMap<String, String> queryMap;
private String Url_Path;

public VideoClient(String BASE_URL) {

    Log.d(TAG,"Base url is "+BASE_URL);
    hostName =getHostNameAndGenerateQueryMap(BASE_URL);

    Gson gson = new GsonBuilder()
            .create();
    RequestInterceptor interceptor = new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {

        }
    };

    restAdapter = new RestAdapter.Builder()
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setEndpoint("http://"+hostName)
            .setClient(new OkClient())
            .setConverter(new GsonConverter(gson))
            .setRequestInterceptor(interceptor)
            .build();

}
private String getHostNameAndGenerateQueryMap(String urlString) {


    Uri uri = Uri.parse(urlString);
    Url_Path = (uri.getPath().startsWith("/")) ? uri.getPath().substring(1) : uri.getPath();
    Set<String> queryParameterNames = uri.getQueryParameterNames();
    String Host = uri.getHost();
    queryMap = new LinkedHashMap<>();

    Iterator<String> iterator = queryParameterNames.iterator();

    while (iterator.hasNext()) {
        String queryName = iterator.next();
        String queryParameter = uri.getQueryParameter(queryName);
        Log.d(TAG,"query name "+queryName +" query param "+queryParameter);

        queryMap.put(queryName, queryParameter);
    }


    return Host;
}


public interface General {

    /*void getVideo(@Path("auth_token") String authId,
                  @Query("et") String systemTime,@Query("service_id") String serviceID,
                  @Query("protocol") String scheme,@Query("play_url") String url,
                  @Query("us") String us,Callback<String> callback);
    */
    @GET("/{path}")
     getVideo(@Path(value="path", encode=false)String path,@QueryMap LinkedHashMap<String, String> queryMap);
}

public void getVideoDetails() {
    Log.i("firing", "getVideoApi");

    Log.d(TAG, "firing " + Url_Path + " function");
    restAdapter.create(General.class).getVideo(Url_Path,queryMap, new Callback<Object>() {
        @Override
        public void success( Object o, Response response) {
            Log.d(TAG," Success Response is "+response );
        }

        @Override
        public void failure(RetrofitError error) {

            Log.d(TAG, "Failure " + "Internal Error" + error);
        }
    });

}

}

1
praveena_kd