无法解析片段中的 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