java - Fragment 无法从 ViewModel 获取值

标签 java android kotlin viewmodel android-viewmodel

我有一个带有jetpack导航的单个 Activity 应用程序,我需要一个对象变量来用于许多 fragment 中的所有应用程序。因此,我使用 ViewModel,并且创建了一个提供 ViewModel 的 Parent Fragment 类:

class MyViewModel : ViewModel() {
    var myData : CustomClass? = null
    ...
}

open class ParentFragment : Fragment {
    val model : MyViewModel by activityViewModels()
    lateinit var myData : CustomClass

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

        model.myData?.let {
            myData = it
        }
    }
}

myData在我使用ParentFragment的地方不应为空,但有时,我会随机得到kotlin.UninitializedPropertyAccessException:lateinit属性myData尚未初始化 当我使用 myData

我的 ViewModel 是否可能不保留 myData?我如何确定我的属性已初始化?

更新:尝试 1

我已经在我的 ParentFragment 中尝试过此代码:

open class ParentFragment : Fragment {
    val model : MyViewModel by activityViewModels()
    lateinit var backingData : CustomClass
    val myData : CustomClass
        get() {
            if (!::backingData.isInitialized)
                model.getData()?.let {
                    backingData = it
                }
            return backingData
        }

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

        model.getData?.let {
            backingData = it
        }
    }
}

但是当我调用myData时,问题并没有消失,似乎是ViewModel丢失了我的数据

更新 2:更多代码详细信息

在进入扩展 ParentFragmentfragment 之前,我在 ViewModel 中设置数据,然后导航到下一个 fragment 如下:

// Inside FirstFragment
if (myData != null) {
    model.setData(myData)
    findNavController().navigate(FirstFragmentDirections.actionFirstToNextFragment())
}

我的 NavController 有可能在设置数据之前进行导航吗?

编辑3:尝试使用自定义应用程序类

根据下面的答案,我实现了一个自定义应用程序类,并且我尝试通过此类传递我的对象:

class MyApplication: Application() {

    companion object {
        var myObject: CustomClass? = null
    }
}

但不幸的是,对我来说没有任何改变。也许我的对象太大而无法正确分配?

最佳答案

试试这个:

class MyViewModel : ViewModel() {
  var myObject : CustomClass? = null
  ...
}

open class ParentFragment : Fragment {
  lateinit var model : MyViewModel by activityViewModels()


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

    model = ViewModelProvider(this).get(MyViewModel::class.java)
    if(model.myObject == null) {
        // initialize myObject, will be persisted by ViewModel
    }
  }
}

请注意,MyViewModel 及其成员对象不应包含对 ActivityFragmentContext,包括对 Context 的任何间接引用,例如 UI View 。

在您的情况下,我不会推荐 LiveData (或 MutableLiveData),因为 LiveData 的一个“功能”是它们的值被发布并且异步更新,因此调用 observe 可能为时已晚。

关于java - Fragment 无法从 ViewModel 获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60845217/

相关文章:

未找到 Android 设备(不知道为什么)

java - Android查看动态大小

java - 颜色无法解析或不是字段

android - 嗨……我一直无法将数据从适配器recyclerview传递到 fragment

java - 在命令行中编译Java程序

来自文件路径的 Java 输入和输出流

java - 假装上传二进制文件而不需要分段

java - 制作一个基本算法——更有趣的版本

android - 为什么不是字符串方法返回 Kotlin.Unit?

android - 如何在 kotlin @Parcelize 中使用 null