kok202
[2019.02.11] Retrofit custom builder

2019. 2. 11. 11:45[정리] 직무별 개념 정리/안드로이드

요구사항

1. 리퀘스트 별로 API 에 호출하기 위한 동일한 데이터 포맷이 존재함.

2. 리퀘스트 별로 매번 Object를 파싱해서 JsonObject로 바꿔줘야하는 것이 유쾌하지 않음

3. 리퀘스트 별로 매번 new Retrofit.builder 하는 과정이 부적절해보임

4. 모든 리퀘스트는 동일한 헤더 포맷을 가짐




Header

 {

"auth-token" : "-", 

"user-token" : "-"

 }

 Body

 {

"request" : {

"userToken" : "-"

"uri" : "-"

"requestTime" : "-"

}

"contents" : {

...

}

 }




요구사항 1

public class RequestDataFormat {
private JsonObject request;
private JsonObject contents;

public RequestDataFormat() {
request = new JsonObject();
}

public void setUserToken(String userToken) {
request.addProperty("userToken", userToken);
}

public void setUri(String uri) {
request.addProperty("uri", uri);
}

public void setRequestTime(String requestTime) {
request.addProperty("requestTime", requestTime);
}

public void setContents(JsonObject contents) {
this.contents = contents;
}
}




요구사항 2 RetrofitBuilder::objectToJsonObject;

요구사항 3 RetrofitBuilder::setRetrofit

요구사항 4

GlobalData의 HOST URL은 Base URL 이며 싱글톤으로 관리함.

OkHttpClient를 통해 클라이언트를 만들고 헤더를 추가함.

Retrofit이 OkHttpClient를 클라이언트로 설정함으로서 Retrofit의 모든 리퀘스트에 헤더를 달아줌

getService시 제네릭을 사용해서 일일히 타입 캐스팅해줘야하는 문제를 해소하고자함.


public class RetrofitBuilder {
private Retrofit retrofit;
private Gson gson;
private JsonParser jsonParser;

private static class RetrofitBuilderHolder {
public static final RetrofitBuilder instance = new RetrofitBuilder();
}

public static RetrofitBuilder getInstance(){
return RetrofitBuilderHolder.instance;
}

private RetrofitBuilder(){
setRetrofit();
setGson();
setJsonParser();
}

private void setRetrofit(){
retrofit = new Retrofit.Builder()
.baseUrl(GlobalData.getInstance().HOST_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(getClientForHeader())
.build();
}

private void setGson(){
gson = new GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeJsonConverter())
.create();
}

private void setJsonParser(){
jsonParser = new JsonParser();
}

private OkHttpClient getClientForHeader(){
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
return httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("auth-token", GlobalData.getInstance().APP_KEY)
.addHeader("user-token", String.valueOf(UserInfo.getInstance().getUid()))
.build();
return chain.proceed(request);
}
}).build();
}

public <GenericOfServiceType> GenericOfServiceType getService(Class argumentClassType) {
return (GenericOfServiceType) retrofit.create(argumentClassType);
}

public JsonObject buildData(String uri, Object contents) {
return objectToJsonObject(getRequestData(uri, contents));
}

private RequestDataFormat getRequestData(String uri, Object contents){
RequestDataFormat requestData = new RequestDataFormat();
requestData.setContents(objectToJsonObject(contents));
requestData.setRequestTime(GlobalData.getInstance().getDate());
requestData.setUserToken(String.valueOf(UserInfo.getInstance().getUid()));
requestData.setUri(uri);
return requestData;
}

private JsonObject objectToJsonObject(Object source){
if(source == null)
return new JsonObject();
String jsonString = gson.toJson(source);
return jsonParser.parse(jsonString).getAsJsonObject();
}
}




사용

String additionalPath = "/member";
JsonObject apiData = RetrofitDataBuilder.getInstance().build(additionalPath, member);
MemberService memberService = RetrofitDataBuilder.getInstance().getService(MemberService.class);
memberService.postMember(apiData).enqueue(new Callback<Member>() {
@Override
public void onResponse(@NonNull Call<Member> call, @NonNull Response<Member> response) {
Log.v("test", response.toString());
}

@Override
public void onFailure(@NonNull Call<BiddingCreation> call, @NonNull Throwable t) {
Log.v("test", t.toString());
}
});