Не удается разрешить конструкцию ViewModelProvider во фрагменте?

Я потратил много времени, пытаясь понять, почему в приведенном ниже коде (ближе к концу) я получаю сообщение об ошибке ViewModelProvider (это). Я также попробовал getActivity () вместо this, та же проблема. Я получаю сообщение об ошибке «Не удается разрешить конструктор ...».


import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;



public class ItemSetupFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_setup, container, false);

        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        ItemSetupFragmentModel model = new ViewModelProvider(this).get(ItemSetupFragmentModel.class);
        model.getKids().observe(this, users -> {
            // update UI
        });
    }
}

Изображение, показывающее ошибку компиляции в Android Studio


person LeaningAndroid    schedule 05.02.2020    source источник
comment
Какую ошибку вы получаете?   -  person Shababb Karim    schedule 05.02.2020
comment
Не удается разрешить конструктор.   -  person LeaningAndroid    schedule 05.02.2020
comment
Это ошибка компиляции.   -  person Shababb Karim    schedule 05.02.2020
comment
какая версия ViewModel включена в build.gradle?   -  person Somesh Kumar    schedule 05.02.2020
comment
Обновленный ответ. Вы должны использовать последнюю версию viewmodel.   -  person Shababb Karim    schedule 05.02.2020


Ответы (4)


Во-первых, вам нужно использовать последнюю версию расширения жизненного цикла. Должен быть:

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0" 

или любая обновленная версия.

Тогда вы должны использовать requireActivity() вместо getActivity(). Таким образом вы убедитесь, что действие прикреплено и не получит NullPointerException.

ItemSetupFragmentModel model = new ViewModelProvider(requireActivity()).get(ItemSetupFragmentModel.class);

Примечание. Обзор модели просмотра и Объявление зависимостей

Мне пришлось перезапустить кеш после добавления библиотеки в файл Gradle. Нет необходимости использовать requireActivity(), достаточно this.

person Shababb Karim    schedule 05.02.2020
comment
Спасибо. Вот и все. Мне пришлось добавить эти строки в свой Gradle. - person LeaningAndroid; 05.02.2020
comment
У меня один и тот же код работает в одном фрагменте и не работает в другом фрагменте. - person nyxee; 03.07.2020
comment
Это по той же проблеме? Убедитесь, что вы используете тот же класс фрагмента из того же пакета или что-то в этом роде. - person Shababb Karim; 04.07.2020

Вы не используете последнюю версию библиотеки, в которую был включен конструктор ViewModelProvider(@NonNull ViewModelStoreOwner owner). Вы просматриваете последние версии документации, но не используете последнюю версию библиотеки ViewModel. Вам нужно использовать

    implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0' // For Java

or

    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' // For kotlin extension
person Somesh Kumar    schedule 05.02.2020

Самая чистая реализация должна использовать Kotlin для своих расширенных функций. Вы можете либо создать этот код kotlin в отдельном классе Kclass, либо оставить этот ответ для будущих пользователей, которые хотят знать, как это сделать в Kotlin. В основном мы инициализируем ViewModel ленивым способом:

Убедитесь, что у вас есть эта зависимость:

implementation "androidx.fragment:fragment-ktx:1.2.0"

Создайте эту вспомогательную функцию, которая обращается к внутреннему методу fragment-ktx, который позволяет вам лениво создавать экземпляр ViewModel:

@MainThread
inline fun <reified VM : ViewModel> Fragment.fragmentViewModel() =
    createViewModelLazy(
        VM::class,
        { this.viewModelStore },
        { ViewModelFactory(Database.getDatabase(requireContext().applicationContext)) }
    )

Теперь создайте ViewModelFactory, используя этот официальный пример java:

https://github.com/android/architecture-components-samples/blob/master/BasicRxJavaSample/app/src/main/java/com/example/android/observability/ui/ViewModelFactory.java < / а>

Или вот вариант Котлина:

class ViewModelFactory(private val database: Database?) : ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>): T {

        requireNotNull(database) { "Database must not be null" }

        return when {

            modelClass.isAssignableFrom(ItemSetupFragmentModel::class.java) -> {
                ItemSetupFragmentModel() as T
            }

            else -> {
                throw IllegalArgumentException("Unknown ViewModel class")
            }
        }
    }
}

А теперь войдите в свой фрагмент и просто инициализируйте свою ViewModel следующим образом

class ItemSetupFragment : Fragment() {

    private val model by viewModel<ItemSetupFragmentModel>()

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

        model.getKids().observe(this, users -> {
            // update UI
        });
    }
}

Надеюсь это поможет!

person M'aiq the Coder    schedule 05.02.2020

Вы должны создать экземпляр своей viewModel:

ItemSetupFragmentModel model = ViewModelProviders.of(this).get(ItemSetupFragmentModel.class);
person Bheem    schedule 05.02.2020
comment
@Bheen, ViewModelPorviders устарел. В документе говорится, что конструкторы ViewModelProvider используются напрямую. - person LeaningAndroid; 05.02.2020