Котлин не понимает ViewModelProviders.of (активность?: Фрагмент) - PullRequest
0 голосов
/ 15 октября 2018

Внутри моего Fragment я инициализирую ViewModel, используя ViewModelProviders.Я хочу, чтобы он взял Activity, если не null, то в противном случае сам (Fragment).

private val viewModel: MainViewModel by lazy {
    ViewModelProviders.of(activity ?: this).get(MainViewModel::class.java)
}

Ни одна из следующих функций не может быть вызвана с предоставленными аргументами.

  • из (Фрагмент), определенный в androidx.lifecycle.ViewModelProviders
  • из (FragmentActivity), определенный в androidx.lifecycle.ViewModelPro

Кажется,язык не позволяет мне вызывать конфликтующие сигнатуры методов (между of(Activity) и of(Fragment). (Это может быть понятно, возможно, компилятор должен ссылаться только на один метод и не может ссылаться на оба на одной и той же строке.) Isчто так?

Теперь мне нужно использовать

    activity?.let {
        ViewModelProviders.of(it).get(MainViewModel::class.java)
    } ?: run {
        ViewModelProviders.of(this).get(MainViewModel::class.java)
    }

Есть ли лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

В дополнение к ответу Jeel, я бы порекомендовал вам, если вам обычно нужно использовать этот шаблон, вы должны определить для него функцию расширения Fragment, чтобы избежать повторения.Например:

fun Fragment.getViewModelProvider() =
    activity?.let(ViewModelProviders::of) ?: ViewModelProviders.of(this)

inline fun <reified T : ViewModel> Fragment.getViewModel() = 
    getViewModelProvider().get(T::class.java)

Оттуда, внутри любого Fragment, вы можете просто позвонить:класс Java специально.

0 голосов
/ 15 октября 2018

Да, это неоднозначность компилятора , потому что вы одновременно передаете activity & this (fragment instance), который имеет различные реализации в ViewModelProviders.

Другой подход для этого заключается в использовании условия when, как показано ниже, (хотя ваш подход также хорош) :

private val viewModel: MainViewModel by lazy {
    return@lazy when {
        activity != null -> {
            ViewModelProviders.of(activity as FragmentActivity).get(MainViewModel::class.java) // you can either pass activity object
        }
        else -> {
            ViewModelProviders.of(this).get(MainViewModel::class.java) // or pass fragment object, both are not possible at same time.
        }
    }
}
...