无法解析片段中的 ViewModelProvider 构造?

Posted

技术标签:

【中文标题】无法解析片段中的 ViewModelProvider 构造?【英文标题】:Cannot resolve ViewModelProvider construction in a fragment? 【发布时间】:2020-05-21 00:56:36 【问题描述】:

我花了很多时间试图弄清楚为什么在下面的代码中(接近尾声),我在 ViewModelProvider(this) 上收到错误。我也试过 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
        );
    

【问题讨论】:

您遇到的错误是什么? 无法解析构造函数。 这是一个编译错误。 build.gradle 中包含什么版本的 ViewModel? 更新了答案。您应该使用最新版本的 viewmodel。 【参考方案1】:

首先,您需要使用最新版本的生命周期扩展。应该是:

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);

注意: ViewModel Overview 和 Declaring Dependencies

将库添加到 Gradle 文件后,我不得不重新启动缓存。 不用requireActivity()this就够了。

【讨论】:

谢谢。就是这样。我必须将这些行添加到我的 Gradle 中。 我有相同的代码在一个片段中工作而在另一个片段中失败。 是同一个问题吗?确保您使用的是来自同一个包或其他东西的同一个片段类。【参考方案2】:

您没有使用包含ViewModelProvider(@NonNull ViewModelStoreOwner owner) 构造函数的最新库版本。您看到的是最新的文档,但没有使用 ViewModel 的最新库版本。 你需要使用

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

    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' // For kotlin extension

【讨论】:

【参考方案3】:

最简洁的实现必须使用 Kotlin 来实现其高级功能。您可以在单独的 Kclass 中创建此 kotlin 代码,也可以将此答案留给想知道如何在 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)) 
    )

现在使用这个官方 java 示例创建一个 ViewModelFactory:

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

或者,这是 Kotlin 的变体:

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
        );
    

希望这会有所帮助!

【讨论】:

【参考方案4】:

您应该通过以下方式实例化您的 viewModel:

ItemSetupFragmentModel model = ViewModelProviders.of(this).get(ItemSetupFragmentModel.class);

【讨论】:

@Bheen,不推荐使用 ViewModelPorviders。文档说直接使用 ViewModelProvider 的构造函数。

以上是关于无法解析片段中的 ViewModelProvider 构造?的主要内容,如果未能解决你的问题,请参考以下文章

当我在导航抽屉中使用带有发送片段的 EditText 时,无法解析片段中的方法“findViewById”? [复制]

无法解析 MvxFramentActivity 中的 SupportFragmentManager

片段中的 JSON 解析 [关闭]

无法在片段中解析方法'recreate()'

使用 BaseAdapter 时片段 TabLayout 中的 NullPointerException

无法解析容器中的存储(React,Redux)