Skip to content

Instantly share code, notes, and snippets.

@matejdro
Last active July 4, 2020 17:22
Show Gist options
  • Save matejdro/4b2323158a5fd2b335c56500a9fee374 to your computer and use it in GitHub Desktop.
Save matejdro/4b2323158a5fd2b335c56500a9fee374 to your computer and use it in GitHub Desktop.
Android Fragment that holds lifecycle for being hidden
import android.os.Bundle
import androidx.annotation.CallSuper
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
/**
* By default [FragmentTransaction.hide] does not trigger any lifecycle events (Fragment is
* still started and resumed even if invisible).
*
* This class provides a solution with [onFragmentDisplayed], [onFragmentHidden] callbacks and
* [visibleViewLifecycle] which is Lifecycle that starts or stops depending on invisibility.
*
* This class is a workaround for the https://github.com/Zhuinden/simple-stack/issues/133
*/
abstract class HidableFragment : Fragment() {
/**
* Lifecycle that based on [onFragmentDisplayed] and [onFragmentHidden] callbacks
*/
protected val visibleViewLifecycle = SimpleLifecycleOwner()
private var activityStarted : Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
visibleViewLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
override fun onStart() {
super.onStart()
activityStarted = true
if (!isHidden) {
onFragmentDisplayed()
}
}
override fun onStop() {
activityStarted = false
if (!isHidden) {
onFragmentHidden()
}
super.onStop()
}
override fun onDestroy() {
visibleViewLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
super.onDestroy()
}
/**
* Callback that gets called whenever fragment is no longer visible to the user,
* either due to whole app not being visible or due to just fragment being invisible
*/
@CallSuper
open fun onFragmentHidden() {
visibleViewLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
/**
* Callback that gets called whenever fragment becomes longer visible to the user,
* either due to whole app becoming visible or due to just fragment being un-hidden
*/
@CallSuper
open fun onFragmentDisplayed() {
visibleViewLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)
}
override fun onHiddenChanged(hidden: Boolean) {
if (hidden) {
if (activityStarted) {
onFragmentHidden()
}
} else if (activityStarted) {
onFragmentDisplayed()
}
}
protected class SimpleLifecycleOwner : LifecycleOwner {
private val lifecycle = LifecycleRegistry(this)
override fun getLifecycle(): Lifecycle {
return lifecycle
}
internal fun handleLifecycleEvent(event: Lifecycle.Event) {
lifecycle.handleLifecycleEvent(event)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment