A recent MVVM revamp of the previous MVP wrapper library found that using rxlifecycle, rxjava to control the lifecycle of Retrofit in MVVM was not necessary, so it was possible to use livedata to manage Retrofit.

So it’s very simple to change that because we don’t need to change much of the Retorit wrapper we just need to get rid of the rxJava wrapper factory, and we need to create a factory that we write ourselves to handle the data, right

Retrofit.Builder.addConverterFactory(GsonConverterFactory.create())
Copy the code
/** * @Description: LiveDataCallAdapterFactory * @Author: gstory **/ public class LiveDataCallAdapterFactory extends CallAdapter.Factory { @Override public CallAdapter<? ,? > get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) ! = LiveData.class) { return null; } Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType); Type rawType = getRawType(observableType); if (rawType ! = ApiResponse.class) { throw new IllegalArgumentException("resource must be ApiResponse"); } if (! (observableType instanceof ParameterizedType)) { throw new IllegalArgumentException("resource must be parameterized"); } return new LiveDataCallAdapter<>(observableType); }}Copy the code
/** * @Description: LiveDataCallAdapter * @Author: gstory * @CreateDate: 2021/4/20 16:00 **/ public class LiveDataCallAdapter<T> implements CallAdapter<T, LiveData<T>> { private Type responseType; LiveDataCallAdapter(Type responseType) { this.responseType = responseType; } @Override public Type responseType() { return responseType; } @Override public LiveData<T> adapt(final Call<T> call) { return new MyLiveData<>(call); } private static class MyLiveData<T> extends LiveData<T> { private AtomicBoolean start = new AtomicBoolean(false); private final Call<T> call; MyLiveData(Call<T> call) { this.call = call; } @Override protected void onActive() { super.onActive(); if (start.compareAndSet(false, true)) { call.enqueue(new Callback<T>() { @Override public void onResponse(@Nullable Call<T> call, @Nullable Response<T> response) { T body = response.body(); postValue(body); } @Override public void onFailure(@Nullable Call<T> call, @nullable Throwable t) {postValue((t) new ApiResponse< t >(0,0, t.getmessage (), null)); }}); }}}}Copy the code

ApiResponse is defined by itself in terms of the business interface, for example

{
    "result": 200,
    "message": "",
    "data": {
        
    }
}
Copy the code

You could write it like this

/** * @Description: ApiResponse * @Author: gstory **/ public class ApiResponse<T> { private int result; private String message; private T data; public ApiResponse(int result, String message, T data) { this.result = result; this.message = message; this.data = data; } public int getResult() { return result; } public void setResult(int result) { this.result = result; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } @Override public String toString() { return "ApiResponse{" + "result=" + result + ", message='" + message + '\'' + ", data=" + data + '}'; }}Copy the code

Note that you need to use LiveData in the server interface, not Call, Observable, etc

/** * @description: interface class * @author: gStory * @createdate: 2021/4/20 16:11 **/ public interface ApiService { @GET("data") LiveData<ApiResponse<MyData>> getData(); }Copy the code

You can then happily call from the ViewModel without worrying about interface leaks

** @return */ public LiveData<ApiResponse<MyData>> getData() {return api.getNetService ().getData(); }Copy the code