前言
Retrofit算是目前最流行的网络框架了,而用的比较多的组合方式是Rxjava+Retrofit,因为RxJava很好的实现了异步通信、UI线程和子线程之间的切换,但是RxJava+Retrofit这一组合有一个缺点,那就是容易造成内存泄漏,因为不能感知UI的生命周期,当然通过加入RxLifeCycle也能解决这一问题。我们今天要说的不是RxLifeCycle,主角是LiveData,下面进入主题。
我们先看LiveData+Retrofit封装,再做分析
LiveData+Retrofit封装
1.添加依赖库
//retrofit
api 'com.squareup.retrofit2:retrofit:2.1.0'
//okhttp
api 'com.squareup.okhttp3:okhttp:3.5.0'
//日志
api 'com.squareup.okhttp3:logging-interceptor:3.6.0'
api 'com.squareup.retrofit2:converter-gson:2.1.0'
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:1.1.0"
// alternatively, just LiveData
implementation "android.arch.lifecycle:livedata:1.1.0"
2.BaseRetrofit
import android.support.annotation.NonNull;
public interface RetrofitWrapper {
/**
* retrofit初始化
*/
void initRetrofit(@NonNull Class tClass);
/**
* 获取http api接口
* @return
*/
T getService();
}
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class BaseRetrofit implements RetrofitWrapper {
private static final String TAG = "BaseRetrofit";
private String url;
private Retrofit retrofit;
private Class tClass;
private T service;
public BaseRetrofit(Class tClass, String url){
this.tClass = tClass;
this.url = url;
initRetrofit(tClass);
}
@Override
public void initRetrofit(Class tClass) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
.readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
.writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor())
.build();
if (!url.endsWith("/")){
url += "/";
}
//创建retrofit实例
retrofit = new Retrofit.Builder()
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(new LiveDataCallAdapterFactory())
.baseUrl(url)
.build();
//创建请求接口实例
service = retrofit.create(tClass);
}
@Override
public T getService() {
if (null == service){
service = retrofit.create(tClass);
}
return service;
}
}
3.LiveDataCallAdapterFactory
import android.arch.lifecycle.LiveData;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;
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("type must be ApiResponse");
}
if (!ParameterizedType.class.isInstance(observableType)){
throw new IllegalArgumentException("resource must be Parameterized");
}
return new LiveDataCallAdapter(observableType);
}
}
其中ApiResponse是请返回的数据结构,一般都是code+msg+data
4.LiveDataCallAdapter
import android.arch.lifecycle.LiveData;
import java.lang.reflect.Type;
import java.util.concurrent.atomic.AtomicBoolean;
import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Callback;
import retrofit2.Response;
public class LiveDataCallAdapter implements CallAdapter> {
private static final String TAG = LiveDataCallAdapter.class.getSimpleName();
private Type responseType;
public LiveDataCallAdapter(Type responseType) {
this.responseType = responseType;
}
@Override
public Type responseType() {
return null;
}
@Override
public LiveData adapt(final Call call) {
return new LiveData(){
AtomicBoolean start = new AtomicBoolean(false);
@Override
protected void onActive() {
super.onActive();
if (start.compareAndSet(false, true)){
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
if (200 == response.code()) {
postValue((T) response.body());
}else {
ApiResponse apiResponse = new ApiResponse(response.code(), response.message(), response.errorBody());
postValue((T) apiResponse);
}
}
@Override
public void onFailure(Call call, Throwable t) {
Log.e(TAG, t.getMessage());
if (responseType == ApiResponse.class){
ApiResponse apiResponse = new ApiResponse(-1, t.getMessage(), null);
postValue((T) apiResponse);
}
}
});
}
}
};
}
}
5.创建api请求接口
import android.arch.lifecycle.LiveData;
import java.util.List;
import retrofit2.http.GET;
public interface BusinessService {
@GET("banner/json")
LiveData>> bannerList();
}
原理剖析
以上就是LiveData+Retrofit完整封装,可以发现与之前Retrofit+RxJava封装对比,除了适配器不一样,Retrofit部分基本一样。不知道大家有没有看到LiveDataCallAdapter中有一行关键代码:postValue();
而这行代码的作用是通过LiveData将请求结果发送到主线程(UI线程)
那么LivaData是如何感知Activity或Fragment生命周期进而防止内存泄漏的呢?我们继续看LiveData源码,发现有下面一段代码:
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
在onStateChanged回调中,判断当前状态是销毁状态时,会移除Observer
/**
* Removes the given observer from the observers list.
*
* @param observer The Observer to receive events.
*/
@MainThread
public void removeObserver(@NonNull final Observer observer) {
assertMainThread("removeObserver");
ObserverWrapper removed = mObservers.remove(observer);
if (removed == null) {
return;
}
removed.detachObserver();
removed.activeStateChanged(false);
}
那又是在什么时候如何订阅的呢?是在相应的activity或fragment中调用LiveData下面方法订阅,订阅之后就可以感知对应的生命周期了。
/**
* Adds the given observer to the observers list within the lifespan of the given
* owner. The events are dispatched on the main thread. If LiveData already has data
* set, it will be delivered to the observer.
*
* The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
* or {@link Lifecycle.State#RESUMED} state (active).
*
* If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
* automatically be removed.
*
* When data changes while the {@code owner} is not active, it will not receive any updates.
* If it becomes active again, it will receive the last available data automatically.
*
* LiveData keeps a strong reference to the observer and the owner as long as the
* given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
* the observer & the owner.
*
* If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
* ignores the call.
*
* If the given owner, observer tuple is already in the list, the call is ignored.
* If the observer is already in the list with another owner, LiveData throws an
* {@link IllegalArgumentException}.
*
* @param owner The LifecycleOwner which controls the observer
* @param observer The observer that will receive the events
*/
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
总结:1.LiveDate+Retrofit封装只需在addCallAdapterFactory方法中加入LiveDataCallAdapter即可;
2.通过LiveData的observer方法订阅之后即可感知相应生命周期;
3.在activity或fragment销毁时移除observer达到防止内存泄漏的作用。
下面是我个人公众号,欢迎关注