add MviBottomSheet

This commit is contained in:
Rinat Nurmukhametov 2021-10-11 15:57:38 +03:00
parent b912ec0ff8
commit 2890cb96ef
2 changed files with 86 additions and 69 deletions

View File

@ -1,78 +1,24 @@
package ru.touchin.roboswag.mvi_arch.core
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.activity.OnBackPressedCallback
import androidx.annotation.LayoutRes
import androidx.annotation.MainThread
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import ru.touchin.mvi_arch.R
import ru.touchin.roboswag.components.utils.setResizableListener
import ru.touchin.roboswag.mvi_arch.di.ViewModelAssistedFactory
import ru.touchin.roboswag.mvi_arch.di.ViewModelFactory
import ru.touchin.roboswag.mvi_arch.marker.ViewAction
import ru.touchin.roboswag.mvi_arch.marker.ViewState
import javax.inject.Inject
abstract class FullscreenBottomSheetDialog<NavArgs, State, Action, VM>(
@LayoutRes private val layoutId: Int
) : BottomSheetDialogFragment(), IMvi<NavArgs, State, Action, VM>
@LayoutRes layoutId: Int
) : MviBottomSheet<NavArgs, State, Action, VM>(layoutId)
where NavArgs : Parcelable,
Action : ViewAction,
State : ViewState,
VM : MviViewModel<NavArgs, Action, State> {
@Inject
lateinit var viewModelMap: MutableMap<Class<out ViewModel>, ViewModelAssistedFactory<out ViewModel>>
protected lateinit var state: NavArgs
protected var bottomSheet: FrameLayout? = null
protected abstract fun injectDependencies()
@MainThread
protected inline fun <reified ViewModel : VM> viewModel(): Lazy<ViewModel> =
lazy {
val fragmentArguments = arguments ?: bundleOf()
ViewModelProvider(
viewModelStore,
ViewModelFactory(viewModelMap, this, fragmentArguments)
).get(ViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.RoundedCornersBottomSheetDialogTheme)
(savedInstanceState ?: arguments)?.getParcelable<NavArgs>(MviFragment.INIT_ARGS_KEY)?.let { savedState ->
state = savedState
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
inflater.inflate(layoutId, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.state.observe(viewLifecycleOwner, Observer(this::renderState))
}
override fun onAttach(context: Context) {
super.onAttach(context)
injectDependencies()
}
override fun onStart() {
super.onStart()
@ -80,21 +26,8 @@ abstract class FullscreenBottomSheetDialog<NavArgs, State, Action, VM>(
bottomSheet?.layoutParams?.height = ViewGroup.LayoutParams.MATCH_PARENT
}
override fun addOnBackPressedCallback(action: Action) {
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
dispatchAction(action)
}
})
}
override fun setupDialog(dialog: Dialog, style: Int) {
dialog.setResizableListener()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(MviFragment.INIT_ARGS_KEY, state)
}
}

View File

@ -0,0 +1,84 @@
package ru.touchin.roboswag.mvi_arch.core
import android.content.Context
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import androidx.lifecycle.Observer
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback
import androidx.annotation.LayoutRes
import androidx.annotation.MainThread
import androidx.core.os.bundleOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import ru.touchin.mvi_arch.R
import ru.touchin.roboswag.mvi_arch.di.ViewModelAssistedFactory
import ru.touchin.roboswag.mvi_arch.di.ViewModelFactory
import ru.touchin.roboswag.mvi_arch.marker.ViewAction
import ru.touchin.roboswag.mvi_arch.marker.ViewState
import javax.inject.Inject
abstract class MviBottomSheet<NavArgs, State, Action, VM>(
@LayoutRes private val layoutId: Int
) : BottomSheetDialogFragment(), IMvi<NavArgs, State, Action, VM>
where NavArgs : Parcelable,
Action : ViewAction,
State : ViewState,
VM : MviViewModel<NavArgs, Action, State> {
@Inject
lateinit var viewModelMap: MutableMap<Class<out ViewModel>, ViewModelAssistedFactory<out ViewModel>>
protected lateinit var state: NavArgs
protected abstract fun injectDependencies()
@MainThread
protected inline fun <reified ViewModel : VM> viewModel(): Lazy<ViewModel> =
lazy {
val fragmentArguments = arguments ?: bundleOf()
ViewModelProvider(
viewModelStore,
ViewModelFactory(viewModelMap, this, fragmentArguments)
).get(ViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.RoundedCornersBottomSheetDialogTheme)
(savedInstanceState ?: arguments)?.getParcelable<NavArgs>(MviFragment.INIT_ARGS_KEY)?.let { savedState ->
state = savedState
}
}
override fun onAttach(context: Context) {
super.onAttach(context)
injectDependencies()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
inflater.inflate(layoutId, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.state.observe(viewLifecycleOwner, Observer(this::renderState))
}
override fun addOnBackPressedCallback(action: Action) {
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
dispatchAction(action)
}
})
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(MviFragment.INIT_ARGS_KEY, state)
}
}