From a86d5b3e61a5bb034dd2d395a290386311c6f50e Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Tue, 18 Aug 2020 05:03:56 -0700 Subject: [PATCH] Remove unnecessary abstractions --- .../magisk/core/base/BaseActivity.kt | 4 +- .../magisk/model/events/EventExecutors.kt | 23 ------ .../magisk/model/events/EventHandler.kt | 25 ------- .../magisk/model/events/SimpleViewEvent.kt | 5 -- .../magisk/model/events/ViewEvents.kt | 16 +++- .../magisk/ui/base/BaseUIActivity.kt | 59 ++++++--------- .../magisk/ui/base/BaseUIComponent.kt | 64 ++++++++++++++++ .../magisk/ui/base/BaseUIFragment.kt | 34 ++++----- .../topjohnwu/magisk/ui/base/BaseViewModel.kt | 4 - .../magisk/ui/base/CompatDelegate.kt | 75 ------------------- .../topjohnwu/magisk/ui/base/CompatView.kt | 16 ---- .../ui/base/{CompatHelpers.kt => Helpers.kt} | 0 .../magisk/ui/surequest/SuRequestActivity.kt | 12 --- 13 files changed, 117 insertions(+), 220 deletions(-) delete mode 100644 app/src/main/java/com/topjohnwu/magisk/model/events/EventExecutors.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/model/events/EventHandler.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/model/events/SimpleViewEvent.kt create mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIComponent.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/base/CompatDelegate.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/base/CompatView.kt rename app/src/main/java/com/topjohnwu/magisk/ui/base/{CompatHelpers.kt => Helpers.kt} (100%) diff --git a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt index be4dc38aa..8416db881 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt @@ -66,7 +66,7 @@ abstract class BaseActivity : AppCompatActivity() { } resultCallbacks[requestCode]?.also { resultCallbacks.remove(requestCode) - it(this@BaseActivity, if (success) 1 else -1, null) + it(this, if (success) 1 else -1, null) } } @@ -75,7 +75,7 @@ abstract class BaseActivity : AppCompatActivity() { super.onActivityResult(requestCode, resultCode, data) resultCallbacks[requestCode]?.also { resultCallbacks.remove(requestCode) - it(this@BaseActivity, resultCode, data) + it(this, resultCode, data) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/model/events/EventExecutors.kt b/app/src/main/java/com/topjohnwu/magisk/model/events/EventExecutors.kt deleted file mode 100644 index 8655aae47..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/model/events/EventExecutors.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.topjohnwu.magisk.model.events - -import android.content.Context -import androidx.fragment.app.Fragment -import com.topjohnwu.magisk.core.base.BaseActivity - -interface ContextExecutor { - - operator fun invoke(context: Context) - -} - -interface ActivityExecutor { - - operator fun invoke(activity: BaseActivity) - -} - -interface FragmentExecutor { - - operator fun invoke(fragment: Fragment) - -} diff --git a/app/src/main/java/com/topjohnwu/magisk/model/events/EventHandler.kt b/app/src/main/java/com/topjohnwu/magisk/model/events/EventHandler.kt deleted file mode 100644 index fc0b4fc62..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/model/events/EventHandler.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.topjohnwu.magisk.model.events - -internal interface EventHandler { - - /** - * Called for all [ViewEvent]s published by associated viewModel. - * For [SimpleViewEvent]s, both this and [onSimpleEventDispatched] - * methods are called - you can choose the way how you handle them. - */ - fun onEventDispatched(event: ViewEvent) {} - - /** - * Called for all [SimpleViewEvent]s published by associated viewModel. - * Both this and [onEventDispatched] methods are called - you can choose - * the way how you handle them. - */ - fun onSimpleEventDispatched(event: Int) {} - - val viewEventObserver get() = ViewEventObserver { - onEventDispatched(it) - if (it is SimpleViewEvent) { - onSimpleEventDispatched(it.event) - } - } -} diff --git a/app/src/main/java/com/topjohnwu/magisk/model/events/SimpleViewEvent.kt b/app/src/main/java/com/topjohnwu/magisk/model/events/SimpleViewEvent.kt deleted file mode 100644 index 4b8c70a87..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/model/events/SimpleViewEvent.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.topjohnwu.magisk.model.events - -class SimpleViewEvent( - val event: Int -) : ViewEvent() \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt b/app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt index 9496f0c9f..43cc88231 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt @@ -3,6 +3,7 @@ package com.topjohnwu.magisk.model.events import android.app.Activity import android.content.Context import android.content.Intent +import androidx.fragment.app.Fragment import com.topjohnwu.magisk.R import com.topjohnwu.magisk.core.Const import com.topjohnwu.magisk.core.base.BaseActivity @@ -32,7 +33,6 @@ import java.lang.reflect.InvocationHandler * Use [ViewEventObserver] for observing these events */ abstract class ViewEvent { - var handled = false } @@ -40,6 +40,18 @@ abstract class ViewEventsWithScope: ViewEvent() { lateinit var scope: CoroutineScope } +interface ContextExecutor { + operator fun invoke(context: Context) +} + +interface ActivityExecutor { + operator fun invoke(activity: BaseActivity) +} + +interface FragmentExecutor { + operator fun invoke(fragment: Fragment) +} + class CheckSafetyNetEvent( private val callback: (SafetyNetResult) -> Unit = {} ) : ViewEventsWithScope(), ContextExecutor, KoinComponent, SafetyNetHelper.Callback { @@ -146,7 +158,7 @@ class CheckSafetyNetEvent( } class ViewActionEvent(val action: BaseActivity.() -> Unit) : ViewEvent(), ActivityExecutor { - override fun invoke(activity: BaseActivity) = activity.run(action) + override fun invoke(activity: BaseActivity) = action(activity) } class OpenChangelogEvent(val item: Repo) : ViewEventsWithScope(), ContextExecutor { diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIActivity.kt index b9253600f..2e17d5ddf 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIActivity.kt @@ -7,26 +7,23 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.res.use -import androidx.core.graphics.Insets import androidx.databinding.DataBindingUtil import androidx.databinding.OnRebindCallback import androidx.databinding.ViewDataBinding import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Observer import androidx.navigation.NavDirections import androidx.navigation.findNavController import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.base.BaseActivity -import com.topjohnwu.magisk.ktx.snackbar import com.topjohnwu.magisk.ktx.startAnimations -import com.topjohnwu.magisk.model.events.EventHandler -import com.topjohnwu.magisk.model.events.SnackbarEvent +import com.topjohnwu.magisk.model.events.ActivityExecutor +import com.topjohnwu.magisk.model.events.ContextExecutor import com.topjohnwu.magisk.model.events.ViewEvent import com.topjohnwu.magisk.ui.theme.Theme -abstract class BaseUIActivity : - BaseActivity(), CompatView, EventHandler { +abstract class BaseUIActivity : + BaseActivity(), BaseUIComponent { protected lateinit var binding: Binding protected abstract val layoutRes: Int @@ -37,12 +34,10 @@ abstract class BaseUIActivity override val viewRoot: View get() = binding.root - override val navigation by lazy { - kotlin.runCatching { findNavController(navHost) }.getOrNull() + open val navigation by lazy { + runCatching { findNavController(navHost) }.getOrNull() } - private val delegate by lazy { CompatDelegate(this) } - open val navHost: Int = 0 open val snackbarView get() = binding.root @@ -66,35 +61,33 @@ abstract class BaseUIActivity(this, layoutRes).apply { - setVariable(BR.viewModel, viewModel) - lifecycleOwner = this@BaseUIActivity + binding = DataBindingUtil.setContentView(this, layoutRes).also { + it.setVariable(BR.viewModel, viewModel) + it.lifecycleOwner = this + it.addOnRebindCallback(object : OnRebindCallback() { + override fun onPreBind(binding: Binding): Boolean { + (binding.root as? ViewGroup)?.startAnimations() + return super.onPreBind(binding) + } + }) } - binding.addOnRebindCallback(object : OnRebindCallback() { - override fun onPreBind(binding: Binding): Boolean { - (binding.root as? ViewGroup)?.startAnimations() - return super.onPreBind(binding) - } - }) + ensureInsets() - delegate.onCreate() - - directionsDispatcher.observe(this, Observer { + directionsDispatcher.observe(this) { it?.navigate() // we don't want the directions to be re-dispatched, so we preemptively set them to null if (it != null) { directionsDispatcher.value = null } - }) + } } override fun onResume() { super.onResume() - delegate.onResume() + viewModel.requestRefresh() } override fun dispatchKeyEvent(event: KeyEvent): Boolean { @@ -102,10 +95,8 @@ abstract class BaseUIActivity snackbar(snackbarView, event.message(this), event.length, event.f) - } + (event as? ContextExecutor)?.invoke(this) + (event as? ActivityExecutor)?.invoke(this) } override fun onBackPressed() { @@ -114,12 +105,6 @@ abstract class BaseUIActivity: LifecycleOwner { + + val viewRoot: View + val viewModel: VM + + fun startObserveEvents() { + viewModel.viewEvents.observe(this) { + onEventDispatched(it) + } + } + + fun consumeSystemWindowInsets(insets: Insets): Insets? = null + + /** + * Called for all [ViewEvent]s published by associated viewModel. + */ + fun onEventDispatched(event: ViewEvent) {} + + fun ensureInsets() { + ViewCompat.setOnApplyWindowInsetsListener(viewRoot) { _, insets -> + insets.asInsets() + .also { viewModel.insets = it } + .let { consumeSystemWindowInsets(it) } + ?.subtractBy(insets) ?: insets + } + if (ViewCompat.isAttachedToWindow(viewRoot)) { + ViewCompat.requestApplyInsets(viewRoot) + } else { + viewRoot.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { + override fun onViewDetachedFromWindow(v: View) = Unit + override fun onViewAttachedToWindow(v: View) { + ViewCompat.requestApplyInsets(v) + } + }) + } + } + + private fun WindowInsetsCompat.asInsets() = Insets.of( + systemWindowInsetLeft, + systemWindowInsetTop, + systemWindowInsetRight, + systemWindowInsetBottom + ) + + private fun Insets.subtractBy(insets: WindowInsetsCompat) = + WindowInsetsCompat.Builder(insets).setSystemWindowInsets( + Insets.of( + insets.systemWindowInsetLeft - left, + insets.systemWindowInsetTop - top, + insets.systemWindowInsetRight - right, + insets.systemWindowInsetBottom - bottom + ) + ).build() + +} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIFragment.kt index db5e844e0..23deb4bfd 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseUIFragment.kt @@ -13,25 +13,26 @@ import androidx.fragment.app.Fragment import androidx.navigation.NavDirections import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.ktx.startAnimations -import com.topjohnwu.magisk.model.events.EventHandler +import com.topjohnwu.magisk.model.events.ActivityExecutor +import com.topjohnwu.magisk.model.events.ContextExecutor +import com.topjohnwu.magisk.model.events.FragmentExecutor import com.topjohnwu.magisk.model.events.ViewEvent -abstract class BaseUIFragment : - Fragment(), CompatView, EventHandler { +abstract class BaseUIFragment : + Fragment(), BaseUIComponent { protected val activity get() = requireActivity() as BaseUIActivity<*, *> protected lateinit var binding: Binding protected abstract val layoutRes: Int override val viewRoot: View get() = binding.root - override val navigation get() = activity.navigation - private val delegate by lazy { CompatDelegate(this) } + private val navigation get() = activity.navigation override fun consumeSystemWindowInsets(insets: Insets) = insets override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - viewModel.viewEvents.observe(this, viewEventObserver) + startObserveEvents() } override fun onCreateView( @@ -39,17 +40,17 @@ abstract class BaseUIFragment(inflater, layoutRes, container, false).apply { - setVariable(BR.viewModel, viewModel) - lifecycleOwner = this@BaseUIFragment + binding = DataBindingUtil.inflate(inflater, layoutRes, container, false).also { + it.setVariable(BR.viewModel, viewModel) + it.lifecycleOwner = this } - return binding.root } override fun onEventDispatched(event: ViewEvent) { - super.onEventDispatched(event) - delegate.onEventExecute(event, this) + (event as? ContextExecutor)?.invoke(requireContext()) + (event as? FragmentExecutor)?.invoke(this) + (event as? ActivityExecutor)?.invoke(activity) } open fun onKeyEvent(event: KeyEvent): Boolean { @@ -61,29 +62,24 @@ abstract class BaseUIFragment() { override fun onPreBind(binding: Binding): Boolean { this@BaseUIFragment.onPreBind(binding) return true } }) - - delegate.onCreate() + ensureInsets() } override fun onResume() { super.onResume() - - delegate.onResume() + viewModel.requestRefresh() } protected open fun onPreBind(binding: Binding) { (binding.root as? ViewGroup)?.startAnimations() } - protected fun ViewEvent.dispatchOnSelf() = delegate.onEventExecute(this, this@BaseUIFragment) - fun NavDirections.navigate() { navigation?.navigate(this) } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseViewModel.kt index eb32ee487..48fecb942 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/base/BaseViewModel.kt @@ -107,10 +107,6 @@ abstract class BaseViewModel( _viewEvents.postValue(this) } - fun Int.publish() { - _viewEvents.postValue(SimpleViewEvent(this)) - } - fun NavDirections.publish() { _viewEvents.postValue(NavigationWrapper(this)) } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/CompatDelegate.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/CompatDelegate.kt deleted file mode 100644 index 75c7a45fc..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/CompatDelegate.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.topjohnwu.magisk.ui.base - -import android.view.View -import androidx.core.graphics.Insets -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.fragment.app.Fragment -import com.topjohnwu.magisk.model.events.ActivityExecutor -import com.topjohnwu.magisk.model.events.ContextExecutor -import com.topjohnwu.magisk.model.events.FragmentExecutor -import com.topjohnwu.magisk.model.events.ViewEvent -import timber.log.Timber - - -class CompatDelegate internal constructor( - private val view: CompatView<*> -) { - - fun onCreate() { - ensureInsets() - } - - fun onResume() { - view.viewModel.requestRefresh() - } - - fun onEventExecute(event: ViewEvent, activity: BaseUIActivity<*, *>) { - (event as? ContextExecutor)?.invoke(activity) - (event as? ActivityExecutor)?.invoke(activity) - (event as? FragmentExecutor)?.let { - Timber.e("Cannot run ${FragmentExecutor::class.java.simpleName} in Activity. Consider adding ${ContextExecutor::class.java.simpleName} as fallback.") - } - } - - fun onEventExecute(event: ViewEvent, fragment: Fragment) { - (event as? ContextExecutor)?.invoke(fragment.requireContext()) - (event as? FragmentExecutor)?.invoke(fragment) - (event as? ActivityExecutor)?.invoke(fragment.requireActivity() as BaseUIActivity<*, *>) - } - - private fun ensureInsets() { - ViewCompat.setOnApplyWindowInsetsListener(view.viewRoot) { _, insets -> - insets.asInsets() - .also { view.peekSystemWindowInsets(it) } - .let { view.consumeSystemWindowInsets(it) } - ?.also { view.viewModel.insets = it } - ?.subtractBy(insets) ?: insets - } - if (ViewCompat.isAttachedToWindow(view.viewRoot)) { - ViewCompat.requestApplyInsets(view.viewRoot) - } else { - view.viewRoot.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { - override fun onViewDetachedFromWindow(v: View) = Unit - override fun onViewAttachedToWindow(v: View) { - ViewCompat.requestApplyInsets(v) - } - }) - } - } - - private fun WindowInsetsCompat.asInsets() = Insets.of( - systemWindowInsetLeft, - systemWindowInsetTop, - systemWindowInsetRight, - systemWindowInsetBottom - ) - - private fun Insets.subtractBy(insets: WindowInsetsCompat) = insets.replaceSystemWindowInsets( - insets.systemWindowInsetLeft - left, - insets.systemWindowInsetTop - top, - insets.systemWindowInsetRight - right, - insets.systemWindowInsetBottom - bottom - ) - -} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/CompatView.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/CompatView.kt deleted file mode 100644 index 11f47e041..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/ui/base/CompatView.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.topjohnwu.magisk.ui.base - -import android.view.View -import androidx.core.graphics.Insets -import androidx.navigation.NavController - -internal interface CompatView { - - val viewRoot: View - val viewModel: ViewModel - val navigation: NavController? - - fun peekSystemWindowInsets(insets: Insets) = Unit - fun consumeSystemWindowInsets(insets: Insets): Insets? = null - -} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/base/CompatHelpers.kt b/app/src/main/java/com/topjohnwu/magisk/ui/base/Helpers.kt similarity index 100% rename from app/src/main/java/com/topjohnwu/magisk/ui/base/CompatHelpers.kt rename to app/src/main/java/com/topjohnwu/magisk/ui/base/Helpers.kt diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt index d800fe7e3..8d090df89 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt @@ -12,9 +12,6 @@ import com.topjohnwu.magisk.R import com.topjohnwu.magisk.core.su.SuCallbackHandler import com.topjohnwu.magisk.core.su.SuCallbackHandler.REQUEST import com.topjohnwu.magisk.databinding.ActivityRequestBinding -import com.topjohnwu.magisk.model.events.DieEvent -import com.topjohnwu.magisk.model.events.ViewActionEvent -import com.topjohnwu.magisk.model.events.ViewEvent import com.topjohnwu.magisk.ui.base.BaseUIActivity import org.koin.androidx.viewmodel.ext.android.viewModel @@ -22,7 +19,6 @@ open class SuRequestActivity : BaseUIActivity event.action(this) - is DieEvent -> finish() - } - } - private fun lockOrientation() { requestedOrientation = if (Build.VERSION.SDK_INT < 18) resources.configuration.orientation