如何将信息从 MutableLiveData<Resource<Object>> 提取到视图模型中的更简单对象

How to extract the information from MutableLiveData<Resource<Object>> to a simpler object in viewmodel

我正在尝试在我的 HomeFragment 中从 MutableLiveData<Resource<ObjectIWant>> 获取一个对象到 var hereIwantTheObject : ObjectIWant,如果您使用协程和 LiveData,显然使用资源 class 是推荐的方法。问题是我希望这个对象在我的变量上并与 MutableLiveData 分离,当我尝试它时它说变量尚未初始化。这是我的 classes 和我尝试过的

ViewModel class:

class HomeFragmentViewModel : ViewModel() {

    val mutableVar: MutableLiveData<Resource<ObjectIwant>> = MutableLiveData()

    init {
        getObjectIwantData()
    }

    fun getObjectIwantData() = viewModelScope.launch {
        mutableVar.postValue(Resource.Loading())
        val response = AppRepository().getObjectIwantDataInRepository()
        mutableVar.postValue(handleResponse(response))
    }

    private fun handleResponse(response: Response<ObjectIwant>): Resource<ObjectIwant> {
        if (response.isSuccessful) {
            response.body()?.let { resultResponse ->
                return Resource.Success(resultResponse)
            }
        }
        return Resource.Error(response.message())
    }

HomeFragment class 以及我试图获取信息的位置:

class HomeFragment : Fragment() {

    lateinit var viewModel: HomeFragmentViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
        viewModel = ViewModelProvider(this).get(HomeFragmentViewModel::class.java)
        binding.lifecycleOwner = this

        var hereIwantTheObject: ObjectIwant? = null

        viewModel.brastlewarkTownData.observe(viewLifecycleOwner, Observer { response ->
            response.data?.let { brastlewarkTown ->
                hereIwantTheObject = brastlewarkTown
            }
        })
        Log.i(TAG, "onCreateView: ${hereIwantTheObject!!.name")
        return binding.root
    }
}

这里是资源 class:

sealed class Resource<T>(
    val data: T? = null,
    val message: String? = null
) {
    class Success<T>(data: T) : Resource<T>(data)
    class Error<T>(message: String, data: T? = null) : Resource<T>(data, message)
    class Loading<T> : Resource<T>()
}

执行 onCreateView() 时,会发生几件事:

  • 本地 var hereIwantTheObject 被声明并用 null
  • 初始化
  • LiveData<Resource<ObjectIwant>> 对象的观察者已注册
  • 局部变量的值仍然是null,但你保证在写入Logcat
  • 时它不是null
  • 所以此时您的应用程序将崩溃...

但为什么 hereIwantTheObject 仍然是 null?这是因为任何 LiveData 对象的观察结果只能在当前函数 onCreateView() 执行完成后进入 UI 线程。

此时局部变量将被丢弃,因此如果您希望稍后能够为其赋值,则需要将其设为 属性:

private var hereIwantTheObject: String? = null

现在,如果您删除带有 hereIwantTheObject 的局部声明的行,并将 Log.i(...) 语句移动到如果 [=] 发生更改时执行的块19=] 对象,一切都会如愿以偿

response.data?.let { brastlewarkTown ->
        hereIwantTheObject = brastlewarkTown
        Log.i(TAG, "onCreateView: ${hereIwantTheObject!!.name}")
    }