Как внедрить viewModel в BaseFragment, используя Koin - PullRequest
2 голосов
/ 15 июня 2019

Я создал абстрактный класс BaseFragment, который будет расширен другими конкретными Fragment классами. Я хочу ввести ViewModel в мой BaseFragment, используя Koin. Вот мой BaseFragment:

abstract class BaseFragment<out VM : BaseViewModel, DB : ViewDataBinding>(private val mViewModelClass: Class<VM>) : Fragment() {

    val viewModel: VM by viewModel()

    open lateinit var binding: DB

    fun init(inflater: LayoutInflater, container: ViewGroup) {
        binding = DataBindingUtil.inflate(inflater, getLayoutRes(), container, false)
    }

    open fun init() {}
    @LayoutRes
    abstract fun getLayoutRes(): Int

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        init(inflater, container!!)
        init()
        super.onCreateView(inflater, container, savedInstanceState)
        return binding.root
    }

    open fun refresh() {}
} 

Но я не могу этого сделать. Я использую 2.0.1 версию Koin.

1 Ответ

1 голос
/ 15 июня 2019

У меня такой же сценарий в моем случае. Вы также можете сделать, как показано ниже:

Добавьте вашу ViewModel в качестве абстрактного и установите значение при расширении BaseFragment.

Мой Базовый фрагмент имеет:

abstract class BaseFragment<Binding : ViewDataBinding, ViewModel : BaseViewModel> : Fragment() {
    protected abstract val mViewModel: ViewModel
    protected lateinit var bindingObject: Binding

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        bindingObject = DataBindingUtil.inflate(inflater, getLayoutResId(), container, false)
        return bindingObject.root
    }

     /**
       * Get layout resource id which inflate in onCreateView.
      */
     @LayoutRes
     abstract fun getLayoutResId(): Int

     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        doDataBinding()
    }

     /**
      * Do your other stuff in init after binding layout.
      */
      abstract fun init()

     private fun doDataBinding() {
       bindingObject.lifecycleOwner = viewLifecycleOwner // it is extra if you want to set life cycle owner in binding
       // Here your viewModel and binding variable imlementation 
       bindingObject.setVariable(BR.viewModel, mViewModel)  // In all layout the variable name should be "viewModel"
       bindingObject.executePendingBindings()
       init()
}

}

Вот моя фактическая реализация фрагмента:

class FragmentComments : BaseFragment<FragmentCommentsBinding, FragmentCommentsVM>() {
// Here is the your viewmodel imlementation 
override val mViewModel: FragmentCommentsVM by viewModel() 

override fun getLayoutResId(): Int = [fragment layout id like "R.layout.fragment_com"]

override fun init() {
...
}

Надеюсь, это поможет вам. Дайте мне знать, если потребуется дополнительная помощь!

...