目录

目录

前言

使用Retrofit+RxJava能够很方便的进行网络请求,并且尤其在线程的调度方面十分便捷,但是这么强大的框架我们要会使用才行如果使用不当很可能导致内存泄露等问题,比如我们Activity或者Fragment中进行网络请求但是还没请求成功我们就关闭了这个界面并且也没有及时进行请求的取消,这样就会导致由于Activity或Fragment没有销毁而产生的内存泄漏,想要避免此类事件的发生就需要我们对RxJava中的订阅进行恰当的管理。

准备工作

首先引入Retrofit+RxJava相关的依赖

implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.9'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
创建Retrofit工具类
object RetrofitUtils {
//这里我是使用的自己本地搭建的测试服务器
private val BASE_URL = "http://192.168.0.137:8080/MPlayer/"
@Volatile
private var mRetrofit: Retrofit? = null
init {
initRetrofit()
}
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { message ->
try {
val msg = URLDecoder.decode(message, "utf-8")
} catch (e: UnsupportedEncodingException) {
e.printStackTrace()
}
})
interceptor.level = HttpLoggingInterceptor.Level.BODY
/**okhttp默认时间10秒 请求时间较长时,重新设置下 */
val builder = OkHttpClient.Builder()
builder.connectTimeout(15, TimeUnit.SECONDS)
builder.readTimeout(20, TimeUnit.SECONDS)
builder.writeTimeout(20, TimeUnit.SECONDS)
builder.retryOnConnectionFailure(true)
val client = builder.build()
mRetrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build()
}
fun getApiServier(reqServer: Class): T {
return mRetrofit!!.create(reqServer)
}
}
创建Api请求接口
interface Api {
@GET("gethomebanner")
fun getHomeBanner(): Observable
@GET("gethomehot")
fun getHomeHot(): Observable
}
创建接收数据的实体类
public class ResultBean {
private int code;
private String msg;
private List data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public List getData() {
return data;
}
public void setData(List data) {
this.data = data;
}
public static class DataBean {
private int bid;
private String videodetailsurl;
private String videoimg;
private String videoname;
public int getBid() {
return bid;
}
public void setBid(int bid) {
this.bid = bid;
}
public String getVideodetailsurl() {
return videodetailsurl;
}
public void setVideodetailsurl(String videodetailsurl) {
this.videodetailsurl = videodetailsurl;
}
public String getVideoimg() {
return videoimg;
}
public void setVideoimg(String videoimg) {
this.videoimg = videoimg;
}
public String getVideoname() {
return videoname;
}
public void setVideoname(String videoname) {
this.videoname = videoname;
}
@Override
public String toString() {
return "DataBean{" +
"bid=" + bid +
", videodetailsurl='" + videodetailsurl + '\'' +
", videoimg='" + videoimg + '\'' +
", videoname='" + videoname + '\'' +
'}';
}
}
}
取消单个订阅
这里我设置的是点击按钮后延时3秒进行请求,并在Activity销毁之后将请求取消,而用来管理请求的正是Observable在订阅完之后所生成的Disposable接口的实现
class MainActivity : AppCompatActivity() {
private lateinit var mDis:Disposable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bt_one.setOnClickListener {
getHomeBanner()//获取首页Banner
}
}
/**
* 获取首页Banner
*/
fun getHomeBanner(){
mDis = RetrofitUtils.getApiServier(Api::class.java)
.getHomeBanner()
.delay(3,TimeUnit.SECONDS)//延时三秒执行请求
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
for (v in it.data){
LogUtils.eTag("首页Banner",v.toString())
}
},{
LogUtils.eTag("首页Banner",it.message)
})
}
override fun onDestroy() {
super.onDestroy()
if(!mDis.isDisposed){
mDis.dispose()//取消订阅
LogUtils.eTag("请求取消","请求已取消")
}
}
}
这时当我们点击发送请求按钮后,如果将Activity关闭则请求会被取消。
而如果我们将onDestroy()方法注释掉后则会继续请求
取消多个订阅
对多个订阅进行管理我们需要使用CompositeDisposable这个类,CompositeDisposable就好像是一个专门用来管理Disposable的集合。我们可以通过add方法将Disposable添加进去然后通过clear()方法取消全部的订阅,具体实现如下,即当我们点击发送请求按钮3秒后请求首页Banner,4秒后请求首页热门。而当我们关闭Activity的时候则会将所以请求取消。
class MainActivity : AppCompatActivity() {
private var mDis:CompositeDisposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bt_one.setOnClickListener {
getHomeBanner()//获取首页Banner
getHomeHot()//获取首页热门
}
}
/**
* 获取首页Banner
*/
fun getHomeBanner(){
mDis.add(RetrofitUtils.getApiServier(Api::class.java)
.getHomeBanner()
.delay(3,TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
for (v in it.data){
LogUtils.eTag("首页Banner",v.toString())
}
},{
LogUtils.eTag("首页Banner",it.message)
}))
}
/**
* 获取首页热门
*/
fun getHomeHot(){
mDis.add(
RetrofitUtils.getApiServier(Api::class.java)
.getHomeHot()
.delay(4,TimeUnit.SECONDS)//延时4秒执行请求
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
for (v in it.data){
LogUtils.eTag("首页热门",v.toString())
}
},{
LogUtils.eTag("首页热门",it.message)
})
)
}
override fun onDestroy() {
super.onDestroy()
mDis.clear()
LogUtils.eTag("请求取消","所有请求已取消")
}
}

同样当我们注释掉onDestroy()方法的时候关闭Activity后请求会依旧执行。