parent
3478f2210a
commit
6852689604
@ -1,14 +1,14 @@ |
||||
package io.legado.app.base |
||||
|
||||
import androidx.lifecycle.ViewModel |
||||
import androidx.viewbinding.ViewBinding |
||||
import io.legado.app.constant.Theme |
||||
|
||||
abstract class VMBaseActivity<VM : ViewModel>( |
||||
layoutID: Int, |
||||
abstract class VMBaseActivity<VB : ViewBinding, VM : ViewModel>( |
||||
fullScreen: Boolean = true, |
||||
theme: Theme = Theme.Auto, |
||||
toolBarTheme: Theme = Theme.Auto |
||||
) : BaseActivity(layoutID, fullScreen, theme, toolBarTheme) { |
||||
) : BaseActivity<VB>(fullScreen, theme, toolBarTheme) { |
||||
|
||||
protected abstract val viewModel: VM |
||||
|
||||
|
@ -0,0 +1,58 @@ |
||||
@file:Suppress("RedundantVisibilityModifier", "unused") |
||||
|
||||
package io.legado.app.utils.viewbindingdelegate |
||||
|
||||
import android.view.View |
||||
import androidx.annotation.IdRes |
||||
import androidx.fragment.app.DialogFragment |
||||
import androidx.lifecycle.LifecycleOwner |
||||
import androidx.viewbinding.ViewBinding |
||||
|
||||
private class DialogFragmentViewBindingProperty<F : DialogFragment, T : ViewBinding>( |
||||
viewBinder: (F) -> T |
||||
) : ViewBindingProperty<F, T>(viewBinder) { |
||||
|
||||
override fun getLifecycleOwner(thisRef: F): LifecycleOwner { |
||||
return if (thisRef.view == null) thisRef.viewLifecycleOwner else thisRef |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Create new [ViewBinding] associated with the [DialogFragment] |
||||
*/ |
||||
@JvmName("viewBindingDialogFragment") |
||||
public fun <F : DialogFragment, T : ViewBinding> DialogFragment.dialogViewBinding( |
||||
viewBinder: (F) -> T |
||||
): ViewBindingProperty<F, T> { |
||||
return DialogFragmentViewBindingProperty(viewBinder) |
||||
} |
||||
|
||||
/** |
||||
* Create new [ViewBinding] associated with the [DialogFragment] |
||||
* |
||||
* @param vbFactory Function that create new instance of [ViewBinding]. `MyViewBinding::bind` can be used |
||||
*/ |
||||
@JvmName("viewBindingDialogFragment") |
||||
public inline fun <F : DialogFragment, T : ViewBinding> DialogFragment.dialogViewBinding( |
||||
crossinline vbFactory: (View) -> T, |
||||
crossinline viewProvider: (F) -> View |
||||
): ViewBindingProperty<F, T> { |
||||
return dialogViewBinding { fragment -> vbFactory(viewProvider(fragment)) } |
||||
} |
||||
|
||||
/** |
||||
* Create new [ViewBinding] associated with the [DialogFragment][this] |
||||
* |
||||
* @param vbFactory Function that create new instance of [ViewBinding]. `MyViewBinding::bind` can be used |
||||
* @param viewBindingRootId Id of the root view from your custom view |
||||
*/ |
||||
@Suppress("unused") |
||||
@JvmName("viewBindingDialogFragment") |
||||
public inline fun <T : ViewBinding> DialogFragment.dialogViewBinding( |
||||
crossinline vbFactory: (View) -> T, |
||||
@IdRes viewBindingRootId: Int |
||||
): ViewBindingProperty<DialogFragment, T> { |
||||
return viewBinding(vbFactory) { fragment: DialogFragment -> |
||||
fragment.dialog!!.window!!.decorView.findViewById(viewBindingRootId) |
||||
} |
||||
} |
@ -0,0 +1,54 @@ |
||||
@file:Suppress("RedundantVisibilityModifier", "unused") |
||||
@file:JvmName("ReflectionFragmentViewBindings") |
||||
|
||||
package io.legado.app.utils.viewbindingdelegate |
||||
|
||||
import android.view.View |
||||
import androidx.annotation.IdRes |
||||
import androidx.fragment.app.Fragment |
||||
import androidx.viewbinding.ViewBinding |
||||
|
||||
private class FragmentViewBindingProperty<F : Fragment, T : ViewBinding>( |
||||
viewBinder: (F) -> T |
||||
) : ViewBindingProperty<F, T>(viewBinder) { |
||||
|
||||
override fun getLifecycleOwner(thisRef: F) = thisRef.viewLifecycleOwner |
||||
} |
||||
|
||||
/** |
||||
* Create new [ViewBinding] associated with the [Fragment] |
||||
*/ |
||||
@JvmName("viewBindingFragment") |
||||
public fun <F : Fragment, T : ViewBinding> Fragment.viewBinding(viewBinder: (F) -> T): ViewBindingProperty<F, T> { |
||||
return FragmentViewBindingProperty(viewBinder) |
||||
} |
||||
|
||||
/** |
||||
* Create new [ViewBinding] associated with the [Fragment] |
||||
* |
||||
* @param vbFactory Function that create new instance of [ViewBinding]. `MyViewBinding::bind` can be used |
||||
* @param viewProvider Provide a [View] from the Fragment. By default call [Fragment.requireView] |
||||
*/ |
||||
@JvmName("viewBindingFragment") |
||||
public inline fun <F : Fragment, T : ViewBinding> Fragment.viewBinding( |
||||
crossinline vbFactory: (View) -> T, |
||||
crossinline viewProvider: (F) -> View = Fragment::requireView |
||||
): ViewBindingProperty<F, T> { |
||||
return viewBinding { fragment: F -> vbFactory(viewProvider(fragment)) } |
||||
} |
||||
|
||||
/** |
||||
* Create new [ViewBinding] associated with the [Fragment] |
||||
* |
||||
* @param vbFactory Function that create new instance of [ViewBinding]. `MyViewBinding::bind` can be used |
||||
* @param viewBindingRootId Root view's id that will be used as root for the view binding |
||||
*/ |
||||
@JvmName("viewBindingFragment") |
||||
public inline fun <T : ViewBinding> Fragment.viewBinding( |
||||
crossinline vbFactory: (View) -> T, |
||||
@IdRes viewBindingRootId: Int |
||||
): ViewBindingProperty<Fragment, T> { |
||||
return viewBinding(vbFactory) { fragment: Fragment -> |
||||
fragment.requireView().findViewById(viewBindingRootId) |
||||
} |
||||
} |
@ -0,0 +1,57 @@ |
||||
@file:Suppress("RedundantVisibilityModifier") |
||||
|
||||
package io.legado.app.utils.viewbindingdelegate |
||||
|
||||
import android.os.Handler |
||||
import android.os.Looper |
||||
import androidx.annotation.MainThread |
||||
import androidx.lifecycle.DefaultLifecycleObserver |
||||
import androidx.lifecycle.Lifecycle |
||||
import androidx.lifecycle.LifecycleOwner |
||||
import androidx.viewbinding.ViewBinding |
||||
import kotlin.properties.ReadOnlyProperty |
||||
import kotlin.reflect.KProperty |
||||
|
||||
public abstract class ViewBindingProperty<in R : Any, T : ViewBinding>( |
||||
private val viewBinder: (R) -> T |
||||
) : ReadOnlyProperty<R, T> { |
||||
|
||||
private var viewBinding: T? = null |
||||
private val lifecycleObserver = ClearOnDestroyLifecycleObserver() |
||||
private var thisRef: R? = null |
||||
|
||||
protected abstract fun getLifecycleOwner(thisRef: R): LifecycleOwner |
||||
|
||||
@MainThread |
||||
public override fun getValue(thisRef: R, property: KProperty<*>): T { |
||||
viewBinding?.let { return it } |
||||
|
||||
this.thisRef = thisRef |
||||
val lifecycle = getLifecycleOwner(thisRef).lifecycle |
||||
if (lifecycle.currentState == Lifecycle.State.DESTROYED) { |
||||
mainHandler.post { viewBinding = null } |
||||
} else { |
||||
lifecycle.addObserver(lifecycleObserver) |
||||
} |
||||
return viewBinder(thisRef).also { viewBinding = it } |
||||
} |
||||
|
||||
@MainThread |
||||
public fun clear() { |
||||
val thisRef = thisRef ?: return |
||||
this.thisRef = null |
||||
getLifecycleOwner(thisRef).lifecycle.removeObserver(lifecycleObserver) |
||||
mainHandler.post { viewBinding = null } |
||||
} |
||||
|
||||
private inner class ClearOnDestroyLifecycleObserver : DefaultLifecycleObserver { |
||||
|
||||
@MainThread |
||||
override fun onDestroy(owner: LifecycleOwner): Unit = clear() |
||||
} |
||||
|
||||
private companion object { |
||||
|
||||
private val mainHandler = Handler(Looper.getMainLooper()) |
||||
} |
||||
} |
Loading…
Reference in new issue