Rxjava
implementation 'io.reactivex:rxjava:1.2.0'
implementation 'io.reactivex:rxandroid:1.2.1'
函数式编程
异步操作
Android
RxJava
通过扩展的观察者模式来实现
4个角色
Observable 被观察者 发射数据
Observer 观察者
Subscriber 观察者 实现回调
Subject 观察者 + 被观察者
通过subscribe实现订阅关系
subscribeOn() 执行线程, 用于指定Observable在哪个线程上面运行,一般指定子线程,如io线程Schedules.io(),kotlin省略写法为io()
observerOn() 回调线程,用于指定Observer发射出去的数据在哪个线程,一般指定主线程AndroidSchedules.MainThread()
场景:各种接口请求回调
package com.example.recycleviewdemo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import rx.Observable
import rx.Scheduler
import rx.Subscriber
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import rx.schedulers.Schedulers.io
class MainActivity : AppCompatActivity() {
companion object {
const val TAG = "RxJava"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
subscriber()
}
private fun subscriber() {
val subscriber = object : Subscriber<String>() {
override fun onNext(t: String?) {
Log.d(TAG, "onNext$t")
}
override fun onCompleted() {
Log.d(TAG, "onCompleted")
}
override fun onError(e: Throwable?) {
Log.d(TAG, "onError")
}
override fun onStart() {
Log.d(TAG, "onStart")
}
}
val observable = Observable.create(Observable.OnSubscribe<String> {
subscriber.onNext("Fage")
subscriber.onNext("HaiLiting")
subscriber.onCompleted()
}).subscribeOn(io())
.observeOn(AndroidSchedulers.mainThread())
observable.subscribe(subscriber)
}
}
操作符
固定时间间隔发射数据 场景:接口轮询
private fun intervalTest() {
Observable.interval(3, TimeUnit.SECONDS)
.subscribe {
runOnUiThread {
Log.d(TAG, "Result$it")
Log.d(TAG, Thread.currentThread().name)
}
}
}
创建指定范围的整数序列的Observable,可用来代替For循环 场景:各种需要for循环的操作
private fun intervalRange() {
Observable.range(0, 60)
.subscribe {
runOnUiThread {
Log.d(TAG, "Result$it")
}
}
}
flatMap 把一个数据集合的每个元素进行操作,输出一个新的集合
private fun flatMap() {
val host = "http://www.baidu.com/"
val list = ArrayList<String>()
list.add("1")
list.add("2")
list.add("3")
list.add("4")
Observable.from(list).flatMap { t ->
Observable.just(host + t) }
.cast(String::class.java)
.subscribe{
Log.d(TAG, "Flapmap=$it")
}
}
filter 过滤操作符号
private fun filterTest() {
for (bean in getData()) {
Observable.just(bean).filter { bean1 ->
bean1.age > 26 }.subscribe {
bean2 ->
Log.d(TAG, "bean=${bean2.age}") }
}
}
组和操作符 场景:多个接口同时发出
Merge 无顺序请求接口
@Override
public void getPlaceAndWeatherData(String place) {
mMainView.showProgress();
PlaceRepository repository = new PlaceRepository();
Context context = BaseApplication.getInstance();
Observable placeObservable = repository.getPlaceList(context);
Observable weatherObservable = ServiceManager.getInstance().getApiService().getWeatherInfo(place, Constants.BAIDU_AK);
Observable.merge(placeObservable, weatherObservable)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Object>() {
@Override
public void onCompleted() {
mMainView.hideProgress();
}
@Override
public void onError(Throwable e) {
mLogger.error(e.getMessage(), e);
mMainView.hideProgress();
}
@Override
public void onNext(Object obj) {
if (obj instanceof List) {
mMainView.setupPlaceData((List<Place>) obj);
} else if (obj instanceof WeatherResponse) {
mMainView.setupWeatherData((WeatherResponse) obj);
}
}
});
}
concat 多个接口同时发出,并且按照顺序返回
@Override
public void getPlaceAndWeatherData(String place) {
mMainView.showProgress();
PlaceRepository repository = new PlaceRepository();
Context context = BaseApplication.getInstance();
Observable placeObservable = repository.getPlaceList(context);
Observable weatherObservable = ServiceManager.getInstance().getApiService().getWeatherInfo(place, Constants.BAIDU_AK);
Observable.concat(placeObservable, weatherObservable)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Object>() {
@Override
public void onCompleted() {
mMainView.hideProgress();
}
@Override
public void onError(Throwable e) {
mLogger.error(e.getMessage(), e);
mMainView.hideProgress();
}
@Override
public void onNext(Object obj) {
if (obj instanceof List) {
mMainView.setupPlaceData((List<Place>) obj);
} else if (obj instanceof WeatherResponse) {
mMainView.setupWeatherData((WeatherResponse) obj);
}
}
});
}
Zip 合并接口 场景:适用于多个接口同时请求,返回的时候合并结果返回
private fun zip() {
val observable1 = Observable.just(1,2,3)
val observable2 = Observable.just(3,4,5)
Observable.zip(observable1, observable2) {
t1, t2 -> t1 + t2
}.subscribe {
Log.d(TAG, it.toString())
Log.d(TAG, Thread.currentThread().name)
}
}
Android常用场景
RxJava + RxAndroid + Okhttp + Retrofit 进行网络请求
implementation 'io.reactivex:rxjava:1.2.0'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.9.0'
interface PlaceService {
@GET("v2/place?token=aioxxxxFsuuj&lang=zh_CN")
fun searchPlaces(@Query("query") query: String): Observable<PlaceResponse>
}
- 在Activity中使用
- 首先写一个BasePresenter主要用来管理RxJava订阅请求
package com.example.recycleviewdemo
import rx.Subscription
import rx.subscriptions.CompositeSubscription
open class BasePresenter {
private val compositeSubscription = CompositeSubscription()
fun addSubscription(sub: Subscription) {
compositeSubscription.add(sub)
}
fun unSubscribe() {
compositeSubscription.unsubscribe()
}
}
- 之后写一个BaseActivity,onDestroy方法中,调用解除订阅方法
package com.example.recycleviewdemo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.orhanobut.logger.AndroidLogAdapter
import com.orhanobut.logger.Logger
abstract class BaseActivity : AppCompatActivity() {
private var mPresenter: BasePresenter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initPresenter()
initView()
setContentView(getContentViewId())
Logger.addLogAdapter(AndroidLogAdapter())
}
protected abstract fun initPresenter()
protected abstract fun initView()
protected abstract fun getContentViewId(): Int
fun setPresenter(presenter: BasePresenter) {
mPresenter = presenter
}
override fun onDestroy() {
super.onDestroy()
mPresenter?.unSubscribe()
Logger.t("fage").d("移除请求")
}
}
package com.example.recycleviewdemo
import retrofit2.Retrofit
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import rx.Subscriber
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
class PlacePresenter: BasePresenter() {
companion object {
const val TAG = "IpPresenter"
}
fun getPlaceInfoFormation() {
val baseUrl = "https://api.caiyunapp.com/"
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
val placeService = retrofit.create(PlaceService::class.java)
val subscription = placeService.searchPlaces("杭州")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Subscriber<PlaceResponse>() {
override fun onNext(t: PlaceResponse) {
Logger.json(TAG, t)
}
override fun onCompleted() {
Logger.d(TAG,"onCompleted")
}
override fun onError(e: Throwable) {
Logger.d(TAG,"onError")
}
})
addSubscription(subscription)
}
}
- 接下来MainActivity中使用 设置Presenter 并发起请求
class MainActivity : BaseActivity() {
private val mPresenter: PlacePresenter by lazy {
PlacePresenter()
}
companion object {
const val TAG = "RxJava"
}
override fun getContentViewId(): Int {
return R.layout.activity_main
}
override fun initPresenter() {
setPresenter(mPresenter)
mPresenter.getPlaceInfoFormation()
}
}
- 可以发现,当我们退出App的时候成功销毁了请求
使用RxBus跨线程、跨Activity、跨Fragment通信
package com.example.rxjavademo.rxbus
import rx.Observable
import rx.subjects.PublishSubject
import rx.subjects.SerializedSubject
import rx.subjects.Subject
object RxBusKotlin {
private var subject: Subject<Any, Any>? = null
init {
subject = SerializedSubject(PublishSubject.create())
}
fun post(obj: Any) {
subject!!.onNext(obj)
}
fun <T> toObservable(eventType: Class<T>): Observable<*> {
return subject!!.ofType(eventType)
}
}
private fun rxbus() {
addSubscription(RxBusKotlin.toObservable(MessageEvent::class.java)
.subscribe{
textView.text = (it as MessageEvent).name
})
}
RxBusKotlin.post(MessageEvent("发哥变了哦"))
package com.example.rxjavademo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.orhanobut.logger.AndroidLogAdapter
import com.orhanobut.logger.Logger
import rx.Subscription
import rx.subscriptions.CompositeSubscription
abstract class BaseActivity : AppCompatActivity() {
private var mPresenter: BasePresenter? = null
private var mRxCompositeSubscription: CompositeSubscription? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mRxCompositeSubscription = CompositeSubscription()
initPresenter()
initView()
setContentView(getContentViewId())
Logger.addLogAdapter(AndroidLogAdapter())
}
protected abstract fun getContentViewId(): Int
protected abstract fun initPresenter()
protected abstract fun initView()
fun setPresenter(presenter: BasePresenter) {
mPresenter = presenter
}
fun addSubscription(sub: Subscription) {
mRxCompositeSubscription!!.add(sub)
}
override fun onDestroy() {
super.onDestroy()
mPresenter?.unSubscribe()
mRxCompositeSubscription?.unsubscribe()
Logger.t("fage").d("移除请求")
}
}