liveDataCallAdapter库 - 实现Retrofit+LiveData具有生命周期的网络请求

269 阅读2分钟

1 关于

  因为最近在用java写一个模仿网易云音乐的博客教程,所以用到了retrofit+rxjava+okhttp3网络框架,因为项目是mvvm框架,所以难免会用到LiveData,它的优势如下:

副本.png

  所以也推荐用LiveData,使用rxjava也可以,就是要考虑一些内存泄漏等问题。

2 添加引用

  项目地址liveDataCallAdapter

  工程build:

allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}

  项目build:

implementation 'com.github.Tobeyr1:liveDataCallAdapter:1.0.2'

3 使用 (支持Java/Kotlin)

  将其添加到你的retrofit的build中:

Retrofit.Builder()
                .client(client)
                .baseUrl(Constant.BaseUrl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addCallAdapterFactory(LiveDataCallAdapterFactory.create()) //add this line to you httpService
                .addConverterFactory(GsonConverterFactory.create())
                .build();

  修改调用api的地方:

@GET("lyric") //获取歌词
    LiveData<ApiResponse<xxxx>> getLyric(@Query("id") long songId);
    //默认使用方法是LiveData<ApiResponse<xxx>>,其中xxx为你自己的实体类

  然后在页面中使用:

  viewModel.getLyric(1111111)
                //lyricEntityApiResponse是根据你的实体类和lib中的apiResonse合成的
                .observe(this, lyricEntityApiResponse -> {
                //可以通过提供的getStatus()方法来判断是返回成功了,还是失败 Status.SUCCESS  Status.ERROR
                //如果失败了,也可以通过getMessage()获取失败信息
                //通过getData()获取实体类数据
                    if (lyricEntityApiResponse.getStatus() == Status.SUCCESS){
                        binding.lrc.loadLrc(lyricEntityApiResponse.getData().getLrc().getLyric(),lyricEntityApiResponse.getData().getTlyric().getLyric());
                    }
                });

  因为是livedata,所以我们可以在这里嵌套调用其他方法,比如请求b的参数基于请求a的结果,但是可以把耗时操作放到viewmodel里面。

  相比较rxjava的调用方式:

               viewModel.login()
                        .compose(RXHelper.observableIO2Main(this))
                        .subscribe(new Observer<LoginEntity>() {
                            @Override
                            public void onSubscribe(Disposable d) {

                            }

                            @Override
                            public void onNext(LoginEntity login_bean) {
                                if (login_bean.getCode() == 200) {
                                }  else {
                                    
                                }

                            }

                            @Override
                            public void onError(Throwable e) {
                            }

                            @Override
                            public void onComplete() {}
                        });

  其中RXHelper.java代码如下:

public class RXHelper {
    public static <T> ObservableTransformer<T, T> observableIO2Main(final Context context) {
        return upstream -> {
            Observable<T> observable = upstream.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread());
            return composeContext(context, observable);
        };
    }

    public static <T> ObservableTransformer<T, T> observableIO2Main(final RxFragment fragment) {
        return upstream -> upstream.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()).compose(fragment.<T>bindToLifecycle());
    }

    public static <T> FlowableTransformer<T, T> flowableIO2Main() {
        return upstream -> upstream
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    private static <T> ObservableSource<T> composeContext(Context context, Observable<T> observable) {
        if(context instanceof RxActivity) {
            return observable.compose(((RxActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
        } else if(context instanceof RxFragmentActivity){
            return observable.compose(((RxFragmentActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
        }else if(context instanceof RxAppCompatActivity){
            return observable.compose(((RxAppCompatActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
        }else {
            return observable;
        }
    }
}