Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Search Gists
Sign in Sign up

Instantly share code, notes, and snippets.

@flyfire
Forked fromAkshayChordiya/ApiResponse.java
CreatedFebruary 3, 2024 01:47
    • Star(0)You must be signed in to star a gist
    • Fork(0)You must be signed in to fork a gist
    Save flyfire/babfec3c719670a12f7a36757bfba154 to your computer and use it in GitHub Desktop.
    LiveData adapter for Retrofit

    Copy the following classes in your project to useLiveData<ApiResponse<T>> instead ofCall<T> in Retrofit services.Made this gist so everyone can just copy and paste them in project rather than finding through the Google Samples.

    Original Credits: I didn't make these classes, they are fromGoogle Sample

    Difference

    Traditional way - withCall:

    interface SomeService {    @GET("data")    fun getData(): Call<T>}

    Traditional way - withLiveData:

    interface SomeService {    @GET("data")    fun getData(): LiveData<ApiResponse<T>>}

    Usage

    Set theLiveDataCallAdapterFactory in the Retrofit Builder

    Retrofit.Builder()        .baseUrl(BASE_URL)        // ....        .addCallAdapterFactory(LiveDataCallAdapterFactory())        // ....        .build()
    importandroid.support.annotation.NonNull;
    importandroid.support.annotation.Nullable;
    importandroid.support.v4.util.ArrayMap;
    importjava.io.IOException;
    importjava.util.Collections;
    importjava.util.Map;
    importjava.util.regex.Matcher;
    importjava.util.regex.Pattern;
    importretrofit2.Response;
    /**
    * Common class used by API responses.
    *
    * @param <T>
    */
    publicclassApiResponse<T> {
    privatestaticfinalPatternLINK_PATTERN =Pattern
    .compile("<([^>]*)>[\\s]*;[\\s]*rel=\"([a-zA-Z0-9]+)\"");
    privatestaticfinalPatternPAGE_PATTERN =Pattern.compile("page=(\\d)+");
    privatestaticfinalStringNEXT_LINK ="next";
    publicfinalintcode;
    @Nullable
    publicfinalTbody;
    @Nullable
    publicfinalStringerrorMessage;
    @NonNull
    publicfinalMap<String,String>links;
    publicApiResponse(Throwableerror) {
    code =500;
    body =null;
    errorMessage =error.getMessage();
    links =Collections.emptyMap();
    }
    publicApiResponse(Response<T>response) {
    code =response.code();
    if (response.isSuccessful()) {
    body =response.body();
    errorMessage =null;
    }else {
    Stringmessage =null;
    if (response.errorBody() !=null) {
    try {
    message =response.errorBody().string();
    }catch (IOExceptionignored) {
    Timber.e(ignored,"error while parsing response");
    }
    }
    if (message ==null ||message.trim().length() ==0) {
    message =response.message();
    }
    errorMessage =message;
    body =null;
    }
    StringlinkHeader =response.headers().get("link");
    if (linkHeader ==null) {
    links =Collections.emptyMap();
    }else {
    links =newArrayMap<>();
    Matchermatcher =LINK_PATTERN.matcher(linkHeader);
    while (matcher.find()) {
    intcount =matcher.groupCount();
    if (count ==2) {
    links.put(matcher.group(2),matcher.group(1));
    }
    }
    }
    }
    publicbooleanisSuccessful() {
    returncode >=200 &&code <300;
    }
    publicIntegergetNextPage() {
    Stringnext =links.get(NEXT_LINK);
    if (next ==null) {
    returnnull;
    }
    Matchermatcher =PAGE_PATTERN.matcher(next);
    if (!matcher.find() ||matcher.groupCount() !=1) {
    returnnull;
    }
    try {
    returnInteger.parseInt(matcher.group(1));
    }catch (NumberFormatExceptionex) {
    Timber.w("cannot parse next page from %s",next);
    returnnull;
    }
    }
    }
    /*
    * Copyright (C) 2017 The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    importandroid.arch.lifecycle.LiveData
    importcom.bitfurther.notigo.student.api.ApiResponse
    importretrofit2.Call
    importretrofit2.CallAdapter
    importretrofit2.Callback
    importretrofit2.Response
    importjava.lang.reflect.Type
    importjava.util.concurrent.atomic.AtomicBoolean
    /**
    * A Retrofit adapter that converts the Call into a LiveData of ApiResponse.
    * @param <R>
    */
    classLiveDataCallAdapter<R>(privatevalresponseType:Type) : CallAdapter<R, LiveData<ApiResponse<R>>> {
    overridefunresponseType():Type {
    return responseType
    }
    overridefunadapt(call:Call<R>):LiveData<ApiResponse<R>> {
    returnobject:LiveData<ApiResponse<R>>() {
    internalvar started=AtomicBoolean(false)
    overridefunonActive() {
    super.onActive()
    if (started.compareAndSet(false,true)) {
    call.enqueue(object:Callback<R> {
    overridefunonResponse(call:Call<R>,response:Response<R>) {
    postValue(ApiResponse(response))
    }
    overridefunonFailure(call:Call<R>,throwable:Throwable) {
    postValue(ApiResponse(throwable))
    }
    })
    }
    }
    }
    }
    }
    /*
    * Copyright (C) 2017 The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    importandroid.arch.lifecycle.LiveData;
    importandroid.support.annotation.NonNull;
    importcom.bitfurther.notigo.student.api.ApiResponse;
    importjava.lang.annotation.Annotation;
    importjava.lang.reflect.ParameterizedType;
    importjava.lang.reflect.Type;
    importretrofit2.CallAdapter;
    importretrofit2.Retrofit;
    publicclassLiveDataCallAdapterFactoryextendsCallAdapter.Factory {
    @Override
    publicCallAdapter<?, ?>get(@NonNullTypereturnType,@NonNullAnnotation[]annotations,@NonNullRetrofitretrofit) {
    if (getRawType(returnType) !=LiveData.class) {
    returnnull;
    }
    TypeobservableType =getParameterUpperBound(0, (ParameterizedType)returnType);
    Class<?>rawObservableType =getRawType(observableType);
    if (rawObservableType !=ApiResponse.class) {
    thrownewIllegalArgumentException("type must be a resource");
    }
    if (!(observableTypeinstanceofParameterizedType)) {
    thrownewIllegalArgumentException("resource must be parameterized");
    }
    TypebodyType =getParameterUpperBound(0, (ParameterizedType)observableType);
    returnnewLiveDataCallAdapter<>(bodyType);
    }
    }
    Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

    [8]ページ先頭

    ©2009-2025 Movatter.jp