Skip to content

Instantly share code, notes, and snippets.

@chrisbanes
Last active September 9, 2022 14:07
Show Gist options
  • Save chrisbanes/152d325211401843326068c24e0d11b1 to your computer and use it in GitHub Desktop.
Save chrisbanes/152d325211401843326068c24e0d11b1 to your computer and use it in GitHub Desktop.
LifecycleObserver which allows easy cancelling of coroutines
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class CoroutineLifecycleObserver : LifecycleObserver {
var job: Job = Job()
private set
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start() {
// If the job is complete (happens after being previously stopped)
// lets create a new one
if (job.isCompleted) {
job = Job()
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun cancel() {
// If the job is active (running) cancel it
if (job.isActive) {
job.cancel()
}
}
}
class DetailFragment : Fragment() {
private val coroutineLifecycle = CoroutineLifecycleObserver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Add observer so any jobs are automatically cancelled
lifecycle.addObserver(coroutineLifecycle)
}
private fun runTask() {
// Set the coroutine parent from LifecycleObserver so that it will
// be automatically cancelled in onStop
launch(parent = coroutineLifecycle.job) {
// do something long-running
}
launch(parent = coroutineLifecycle.job) {
// do something else long-running
}
// both of these will be cancelled in onStop (if still running)
}
}
@michelonwordi
Copy link

Great stuff!! Although, this only works if you're launching coroutines in a fragment or Activity. How could this be applied if you launch your coroutines in another component that's lifecycle agnostic, e.g presenter?

@chrisbanes
Copy link
Author

chrisbanes commented Sep 7, 2018

@michelonwordi It works with anything which exposes a LifecycleOwner, so your presenter could easily expose one of those. You then just add this observer to it.

@randallmitchell
Copy link

This looks like a great use case for inclusion in a base activity... given it supports business rules but doesn't in itself implement any. Thanks!

My impression here is that we should call runTask in onStart. Is that correct?

@TemMax
Copy link

TemMax commented Sep 10, 2018

In this case I need to add arch dependency to my project?

@omarmiatello
Copy link

There is a new approach: "Structured concurrency"
https://medium.com/@elizarov/structured-concurrency-722d765aa952

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment