LoginSignup
88
89

More than 5 years have passed since last update.

Retrofitでアレをやりたい時のTips

Last updated at Posted at 2014-12-11

AndroidでAPIとやり取りするライブラリとして、Square社のRetrofitがあります。
こんな感じでとても簡潔に処理が記述できます。

MainApplication.API.getUsers(new Callback<List<User>>() {
    @Override
    public void failure(RetrofitError e) {
        //
    }

    @Override
    public void success(List<User> users, Response response) {
        //
    }
});

メリットをまとめるとこんな感じです。

  • Callbackクラスのインターフェースメソッドがわかりやすくていい感じ。
  • URLを各処理の中ではなく別のクラスにまとめて書いておくことができて見通しがいい。
  • Gsonでのparseも初期化処理で記述しておけば各処理の中で書かなくていい。
  • RestAdapterというクラスを使うことでDIしやすくなる。
  • モック用のライブラリも梱包されておりテストも書きやすい。

便利なんですが、実際に使う場合にアレどうやったらいいの?ってことがあったのでまとめておこうと思います。

1. Gsonなどでconvertする前に何か処理をしたい

初期化時に、setConverterで独自のCoverterクラスをセットします。ちょっと汚いですが。。

public static final ApiService API = new RestAdapter.Builder()
            .setEndpoint("")
            .setConverter(new CustomGsonConverter())
            .build()
            .create(ApiService.class);
public class CustomGsonConverter extends GsonConverter {

    private Gson gson;

    public CustomGsonConverter() {
        this(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create());
    }

    public ApiGsonConverter(Gson gson) {
        super(gson);
        this.gson = gson;
    }

    @Override
    public Object fromBody(TypedInput body, Type type) throws ConversionException {
        String charset = "UTF-8";
        if (body.mimeType() != null) {
            charset = MimeUtil.parseCharset(body.mimeType());
        }

        InputStreamReader isr = null;
        try {
            ByteArrayOutputStream baos = inputStreamToOutputStream(body.in());

            // ここで何かする

            isr = new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()), charset);
            return gson.fromJson(isr, type);
        } catch (IOException e) {
            throw new ConversionException(e);
        } catch (JsonParseException e) {
            throw new ConversionException(e);
        } finally {
            if (isr != null) {
                try {
                    isr.close();
                } catch (IOException ignored) {
                }
            }
        }
    }

2. 通信時にsession_store_keyを仕込みたい

初期化時に、setRequestInterceptorで独自のInterceptorクラスをセットします。

public static final ApiService API = new RestAdapter.Builder()
            .setEndpoint("")
            .setRequestInterceptor(new CustomRequestInterceptor())
            .build()
            .create(ApiService.class);
public class CustomRequestInterceptor implements RequestInterceptor {

    private static final String HEADER_COOKIE = "Cookie";
    private static final String EQ = "=";

    @Override
    public void intercept(RequestInterceptor.RequestFacade request) {
        request.addHeader(HEADER_COOKIE, Constants.SESSION_STORE_KEY + EQ + "sessionId");
    }
}

3. 通信エラーが起きた時に共通処理をしたい

初期化時に、setErrorHandlerで独自のErrorHandlerクラスをセットします。

public static final ApiService API = new RestAdapter.Builder()
            .setEndpoint("")
            .setErrorHandler(new CustomErrorHandler())
            .build()
            .create(ApiService.class);
public class CustomErrorHandler implements ErrorHandler {

    @Override
    public Throwable handleError(RetrofitError cause) {
        try {
            Response response = cause.getResponse();
            // ここで何かする
        } catch (Exception e) {
            //
        }
        return cause;
    }
}

4. 通信時間を計測したい

初期化時に、setProfilerで独自のProfilerクラスをセットします。

public static final ApiService API = new RestAdapter.Builder()
            .setEndpoint("")
            .setProfiler(new CustomProfiler())
            .build()
            .create(ApiService.class);
public class CustomProfiler implements Profiler {
    @Override
    public Object beforeCall() {
        // afterCallに渡したいデータがあればここで返す
        return null;
    }

    @Override
    public void afterCall(RequestInformation requestInfo, long elapsedTime,
                          int statusCode, Object beforeCallData) {
        try {
            // ここで何かする。beforeCallDataには、beforeCall()で返されたObjectが入る
        } catch (Exception e) {
            //
        }
    }
}
88
89
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
88
89