최근에 Retrofit 2를 사용하기 시작했고 빈 응답 본문을 구문 분석하는 문제에 직면했습니다. 응답 본문 내부에 내용이없는 http 코드로만 응답하는 서버가 있습니다.
서버 응답 (헤더, 상태 코드 등)에 대한 메타 정보 만 처리하려면 어떻게해야합니까?
최근에 Retrofit 2를 사용하기 시작했고 빈 응답 본문을 구문 분석하는 문제에 직면했습니다. 응답 본문 내부에 내용이없는 http 코드로만 응답하는 서버가 있습니다.
서버 응답 (헤더, 상태 코드 등)에 대한 메타 정보 만 처리하려면 어떻게해야합니까?
답변:
편집하다:
Jake Wharton이 지적했듯이
@GET("/path/to/get")
Call<Void> getMyData(/* your args here */);
내 원래 응답에 비해 가장 좋은 방법입니다.
을 반환 ResponseBody
하면 응답 구문 분석을 우회 할 수 있습니다 .
@GET("/path/to/get")
Call<ResponseBody> getMyData(/* your args here */);
그런 다음 전화로
Call<ResponseBody> dataCall = myApi.getMyData();
dataCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Response<ResponseBody> response) {
// use response.code, response.headers, etc.
}
@Override
public void onFailure(Throwable t) {
// handle failure
}
});
Void
. 사용겠습니까 Unit
코 틀린 코드는 동일한 혜택을 제공 Void
개조를위한 자바를?
Unit
Kotlin에서 작동 Void
하지 않지만 작동 합니다. 어딘가에 하드 코딩 된 수표가 있다고 가정합니다.
RxJava를 사용 Completable
하는 경우이 경우 에 사용하는 것이 좋습니다.
값없이 지연된 계산을 나타내지 만 완료 또는 예외에 대한 표시 만 나타냅니다. 이 클래스는 Reactive-Streams와 유사한 이벤트 패턴을 따릅니다. onSubscribe (onError | onComplete)?
http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Completable.html
받아 들여진 대답에서 :
@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);
엔드 포인트가 실패 응답 코드를 반환하는 경우에도 여전히에 있으며 onNext
응답 코드를 직접 확인해야합니다.
그러나 Completable
.
@GET("/path/to/get")
Completable getMyData(/* your args here */);
당신은 단지 것 onComplete
하고 onError
. 응답 코드가 성공하면 onComplete
다른 코드가 실행됩니다 onError
.
onError
Throwable
논쟁에는 무엇이 포함됩니까? 나는 이것이 더 깨끗하다고 생각하지만 우리는 종종 실패에 대한 응답 코드와 본문을 살펴 봐야합니다.
rxjava를 사용하는 경우 다음과 같이 사용하십시오.
@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);
다음은 PUT REST 요청과 함께 Rx2 및 Retrofit2와 함께 사용한 방법입니다. 내 요청에는 json 본문이 있지만 본문이 비어있는 http 응답 코드 만 있습니다.
Api 클라이언트 :
public class ApiClient {
public static final String TAG = ApiClient.class.getSimpleName();
private DevicesEndpoint apiEndpointInterface;
public DevicesEndpoint getApiService() {
Gson gson = new GsonBuilder()
.setLenient()
.create();
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClientBuilder.addInterceptor(logging);
OkHttpClient okHttpClient = okHttpClientBuilder.build();
apiEndpointInterface = new Retrofit.Builder()
.baseUrl(ApiContract.DEVICES_REST_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(DevicesEndpoint.class);
return apiEndpointInterface;
}
인터페이스 :
public interface DevicesEndpoint {
@Headers("Content-Type: application/json")
@PUT(ApiContract.DEVICES_ENDPOINT)
Observable<ResponseBody> sendDeviceDetails(@Body Device device);
}
그런 다음 사용하려면 :
private void sendDeviceId(Device device){
ApiClient client = new ApiClient();
DevicesEndpoint apiService = client.getApiService();
Observable<ResponseBody> call = apiService.sendDeviceDetails(device);
Log.i(TAG, "sendDeviceId: about to send device ID");
call.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<ResponseBody>() {
@Override
public void onSubscribe(Disposable disposable) {
}
@Override
public void onNext(ResponseBody body) {
Log.i(TAG, "onNext");
}
@Override
public void onError(Throwable t) {
Log.e(TAG, "onError: ", t);
}
@Override
public void onComplete() {
Log.i(TAG, "onCompleted: sent device ID done");
}
});
}
Void
더 나은 의미를 가질뿐만 아니라 빈 케이스에서 (약간) 더 효율적이고 비어 있지 않은 케이스에서 훨씬 더 효율적입니다 (몸에 관심이 없을 때).