Why do lifecycle management
Using RxJava this library development has been for many years, from the beginning of the use to now also experienced a lot of stages, the middle also encountered a lot of problems, today we have a good chat on the life cycle of RxJava.
- How to use RxJava?
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
// onNext
}, {
// onError
})
Copy the code
- This is a simple asynchronous processing, but it can’t be done just like this, because during Android development, if you are doing a time-consuming operation and the operation is not finished, then you can exit the current Activity. The processing of this code does not end with the exit of the Activity, which can cause problems such as memory leaks and, in severe cases, even the APP to flash back.
How do you manage the life cycle
So how do you manage the RxJava life cycle? RxJava provides us with the CompositeDisposable class for managing RxJava.
val disposable = Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
// onNext
}, {
// onError
})
val disposables = CompositeDisposable()
disposables.add(disposable)
disposables.clear()
Copy the code
- Every time I useRxJavaWill generate it
Disposable
Object added toCompositeDisposable
Object, and at the end of each interfaceCompositeDisposable
The object’sclear()
Method to cancel the event. - In newer versionsRxJavaDuring use, we will find that if there is no on
subscribe
Method to process,studio
I would have issued an amber alert becauseRxJava 在subscribe
Method adds@CheckReturnValue
Annotation, asking us to process its return value.
This is my first phase of processing, adding CompositeDisposable every time I use RxJava and processing it in the Activity’s onDestroy method.
The first version of easy administration
It follows from the above processing that the related operations are encapsulated in a base class, providing a method addDisposable to add RxJava requests to lifecycle management. Later, using the ViewModel in Google Jetpack, we put the final cleared action into the onCleared method of the ViewModel.
- However, these treatments have one problem in common, and that is a lack of elegance.
addDisposable(
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
// onNext
}, {
// onError}))val disposable = Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
// onNext
}, {
// onError
})
addDisposable(disposable)
Copy the code
- Every time in useRxJavaIs called
addDisposable
Once or twice is nothing, but if the project is used too much, it will feel tedious, so I have the idea to optimize it. - The first idea is how to make it complete the lifecycle management binding in the process of chain calls.
- This would require us to add methods to the RxJava class, which is of course not possible in Java development. We cannot modify the RxJava source code, but in Kotlin we can use extension methods to achieve this effect.
- First, to manage the lifecycle uniformly, we need to extract the lifecycle management-related methods into an interface:
interface RxLifecycleOwner {
/** RxJ lifecycle management */
var disposables: CompositeDisposable?
/** * Add Rx to lifecycle management */
fun addDisposable(dis: Disposable){ disposables? .add(dis) }/** * processes all events added to lifecycle management */
fun disposeAll(a){ disposables? .clear() disposables =null}}Copy the code
- Methods of interfaces in Kotlin can be implemented by default.
- Then add the extension method:
/** * Subscribe and associate lifecycle management **@paramOwner Rx Lifecycle management interface *@paramOnNext Event handling *@paramOnComplete event completes *@paramOnSubscribe Event subscription * *@return[Disposable] Event object */
fun <T> Observable<T>.subscribeWithOwner(owner: RxLifecycleOwner,
onNext: Consumer<T> = Functions.emptyConsumer(),
onError: Consumer<Throwable> = Functions.ON_ERROR_MISSING,
onComplete: Action = Functions.EMPTY_ACTION,
onSubscribe: Consumer<Disposable> = Functions.emptyConsumer()
): Disposable {
val disposable = this.subscribe(onNext, onError, onComplete, onSubscribe)
owner.addDisposable(disposable)
return disposable
}
/** * Subscribe and associate lifecycle management **@paramOwner Rx Lifecycle management interface *@paramObserver The observer object */
fun <T> Observable<T>.subscribeWithOwner(owner: RxLifecycleOwner,
observer: Observer<T>) {
this.subscribe(object : Observer<T> {
override fun onComplete(a) {
observer.onComplete()
}
override fun onSubscribe(d: Disposable) {
observer.onSubscribe(d)
owner.addDisposable(d)
}
override fun onNext(t: T) {
observer.onNext(t)
}
override fun onError(e: Throwable) {
observer.onError(e)
}
})
}
Copy the code
- When used, only implementation is required
RxLifecycleOwner
Interface and initializeCompositeDisposable
Objects will do.
class BaseViewModel
: ViewModel(), RxLifeCycleOwner {
/** Rx lifecycle management */
override var disposables: CompositeDisposable? = CompositeDisposable()
override fun onCleared(a) {
// Handle Rx events
disposeAll()
}
}
class MainViewModel : BaseViewModel() {
fun doSomething(a) {
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWithOwner(this, {
// onNext
}, {
// onError}}})Copy the code
- This completes the first release, requiring no extra code each time RxJava is used, and life cycle management can be chain-called.
The second version of easy administration
After the above operation, we have to simplify the RxJava lifecycle management, but still feel complicated how to do, why every use of RxLifecycleOwner interface to implement oh, every time to manually cancel the event, so troublesome look, is there a better solution? At this time, LiveData gave me inspiration.
- As we all know,
LiveData
It’s life cycle aware. He has one inside himLifecycleBoundObserver
Class, by implementationLifecycleEventObserver
The interface implements the pairThe Activity and fragmentsLife cycle perception,LifecycleEventObserver
There areonStateChanged
The method will be inThe Activity and fragmentsAfter the lifecycle method is called back, the next operation is then performed.
/** * Rx lifecycle observer **@paramLifecycleOwner Android lifecycle management interface */
class RxLifecycleObserver(lifecycleOwner: LifecycleOwner) : LifecycleEventObserver, RxLifecycleOwner {
override var disposables: CompositeDisposable? = null
init {
disposables = CompositeDisposable()
// Add the current observer object to Android lifecycle management
lifecycleOwner.lifecycle.addObserver(this)}override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (source.lifecycle.currentState == Lifecycle.State.DESTROYED) {
// The lifecycle goes to onDestroy, consuming all events
disposeAll()
// Remove the observer
source.lifecycle.removeObserver(this)
// Remove the reference from the collection
rxLifecycles.remove(source)
}
}
}
Copy the code
- You might not be able to find it in some places
LifecycleOwner
, but there is a need for life cycle management, so it is retainedRxLifecycleOwner
Interface.
/** * HashMap object, save Rx, Android life cycle management object */
internal val rxLifecycles = hashMapOf<LifecycleOwner, RxLifecycleObserver>()
/** * Get the Rx lifecycle management object ** based on the Android lifecycle object@paramOwner Android life cycle object * *@returnRx lifecycle management object */
internal fun getObserver(owner: LifecycleOwner): RxLifecycleObserver {
var observer: RxLifecycleObserver?
if (rxLifecycles.containsKey(owner)) {
// The collection already contains the observer object
observer = rxLifecycles[owner]
if(observer ! =null) {
// And is not empty, returns the existing observer object
return observer
}
}
// If no existing observer exists, create a new observer object
observer = RxLifecycleObserver(owner)
// Add to Map collection for reuse
rxLifecycles[owner] = observer
return observer
}
Copy the code
- Use Map collections to hold observer objects for reuse.
/** * Subscribe and associate lifecycle management **@paramOwner Android Life cycle interface *@paramOnNext Event handling *@paramOnComplete event completes *@paramOnSubscribe Event subscription * *@return[Disposable] Event object */
fun <T> Observable<T>.subscribeWithOwner(owner: LifecycleOwner,
onNext: Consumer<T> = Functions.emptyConsumer(),
onError: Consumer<Throwable> = Functions.ON_ERROR_MISSING,
onComplete: Action = Functions.EMPTY_ACTION,
onSubscribe: Consumer<Disposable> = Functions.emptyConsumer()
): Disposable {
val disposable = this.subscribe(onNext, onError, onComplete, onSubscribe)
getObserver(owner).addDisposable(disposable)
return disposable
}
/** * Subscribe and associate lifecycle management **@paramOwner Android Life cycle interface *@paramObserver The observer object */
fun <T> Observable<T>.subscribeWithOwner(owner: LifecycleOwner,
observer: Observer<T>) {
this.subscribe(object : Observer<T> {
override fun onComplete(a) {
observer.onComplete()
}
override fun onSubscribe(d: Disposable) {
observer.onSubscribe(d)
getObserver(owner).addDisposable(d)
}
override fun onNext(t: T) {
observer.onNext(t)
}
override fun onError(e: Throwable) {
observer.onError(e)
}
})
}
Copy the code
- It’s easier to use.
class MainActivity : AppCompatActivity() {
fun doSomething(a) {
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWithOwner(this, {
// onNext
}, {
// onError}}})Copy the code
- Used in Activity.
class BaseViewModel : ViewModel(), LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
when (event) {
Lifecycle.Event.ON_CREATE -> onCreate(source)
Lifecycle.Event.ON_START -> onStart(source)
Lifecycle.Event.ON_RESUME -> onResume(source)
Lifecycle.Event.ON_PAUSE -> onPause(source)
Lifecycle.Event.ON_STOP -> onStop(source)
Lifecycle.Event.ON_DESTROY -> onDestroy(source)
Lifecycle.Event.ON_ANY -> {
}
}
}
}
class MainViewModel : BaseViewModel() {
override fun onCreate(source: LifecycleOwner) {
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWithOwner(source, {
// onNext
}, {
// onError}}})Copy the code
The last
- There you have it, a complete RxJava lifecycle processing, less than 300 lines of code.
- Welcome to Github address here.