Reputation: 2431
When writing Views
, ViewModels
and LiveData
are lifecycle aware. The ViewModel
want's the current FragmentActivity
, LiveData
the current LifecycleOwner
. You don't know in advance if your View will be wrapped or somewhat. So it requires a flexible function to to find the wanted context. I ended up with this two methods:
private FragmentActivity getFragmentActivity() {
Context context = getContext();
while (!(context instanceof FragmentActivity)) {
context = ((ContextWrapper) context).getBaseContext();
}
return (FragmentActivity) context;
}
private LifecycleOwner getLifecycleOwner() {
Context context = getContext();
while (!(context instanceof LifecycleOwner)) {
context = ((ContextWrapper) context).getBaseContext();
}
return (LifecycleOwner) context;
}
Now this is a lot of boilerplate code to put into each View. Is there a more easy way?
I don't want to use a customised View base class for this, as large hierarchy's are ugly. Composition on the other hand requires as much code as this solution.
Upvotes: 24
Views: 29205
Reputation: 533
you can find it
lifecycle-runtime-ktx
:
fun View.findViewTreeLifecycleOwner(): LifecycleOwner? = ViewTreeLifecycleOwner.get(this)
Upvotes: 27
Reputation: 1829
Similar to another answer, but without needing to specify maxDepth:
val Context.lifecycleOwner: LifecycleOwner?
get() {
var context: Context? = this
while (context != null && context !is LifecycleOwner) {
val baseContext = (context as? ContextWrapper?)?.baseContext
context = if (baseContext == context) null else baseContext
}
return if (context is LifecycleOwner) context else null
}
Upvotes: 2
Reputation: 629
Kotlin Extensions
fun Context.fragmentActivity(): FragmentActivity? {
var curContext = this
var maxDepth = 20
while (--maxDepth > 0 && curContext !is FragmentActivity) {
curContext = (curContext as ContextWrapper).baseContext
}
return if(curContext is FragmentActivity)
curContext
else
null
}
fun Context.lifecycleOwner(): LifecycleOwner? {
var curContext = this
var maxDepth = 20
while (maxDepth-- > 0 && curContext !is LifecycleOwner) {
curContext = (curContext as ContextWrapper).baseContext
}
return if (curContext is LifecycleOwner) {
curContext as LifecycleOwner
} else {
null
}
}
Usage
val lifecycleOwner = context.lifecycleOwner()
val fragmentActivity = context.fragmentActivity()
Upvotes: 6
Reputation: 1511
If you don't want to use composition you can put this into common BaseView class. Alternatively, you can make it a static method in some utils class.
If you use Kotlin you can also make it Kotlin extension function, what is my most favourite way of doing that.
Upvotes: 0