绑定适配器实时数据值始终为null [英] Binding Adapter live data value is always null

查看:54
本文介绍了绑定适配器实时数据值始终为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于某些原因,两个绑定适配器的第二个参数值始终返回null,我无法弄清原因.我从概述片段的RecyclerView中选择一个 plantIndividual ,并使用它导航到详细信息页面-单个片段.两个片段共享一个viewModel.

For some reason, the second parameter value for both binding Adapters always returns null and I cannot figure out why. I am selecting a plantIndividual from a RecyclerView in the overview fragment and using it to navigate to a details page - individual fragment. Both Fragments share a viewModel.

这是我的BindingAdapters:

Here are my BindingAdapters:

@BindingAdapter("listPhotoData")
fun bindPlantRecyclerView(recyclerView: RecyclerView,
                 data: List<PlantPhoto>?) {
val adapter = recyclerView.adapter as CollectionIndividualAdapter
adapter.submitList(data)
}

@BindingAdapter("singleImage")
fun loadImage(imgView: ImageView, imgUrl: File) {
imgUrl.let {
    Glide.with(imgView.context)
        .load(imgUrl)
        .apply(
            RequestOptions()
                .placeholder(R.drawable.loading_animation)
                .error(R.drawable.ic_broken_image))
        .into(imgView)
    }
}

我的详细信息片段布局:

My details fragment layout:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="viewModel"
            type="com.example.collection.presentation.overview.CollectionOverviewViewModel" />
        <variable
            name="plantPhoto"
            type="com.example.storage.data.PlantPhoto" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true">

        <ImageView
            android:id="@+id/collection_individual_imageview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:singleImage="@={viewModel.plantPhotoDisplay.plantFilePath}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.26999998"
            tools:srcCompat="@tools:sample/avatars" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/collection_individual_recyclerview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/collection_individual_imageview"
            app:layout_constraintVertical_bias="0.498"
            app:listPhotoData="@={viewModel.listPlantPhoto}"
            tools:listitem="@layout/image_plant_photo_view" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

ViewModel:

ViewModel:

class CollectionOverviewViewModel(application: Application) : AndroidViewModel(application) {

lateinit var mediaPlantList: MutableList<File>
private var newPhotoList = mutableListOf<PlantPhoto>()

private val context = getApplication<Application>().applicationContext

private val _navigateToSelectedPlant = MutableLiveData<PlantIndividual>()
val navigateToSelectedPlant: LiveData<PlantIndividual>
    get() = _navigateToSelectedPlant

private val _listPlantPhoto = MutableLiveData<MutableList<PlantPhoto>>()
val listPlantPhoto: LiveData<MutableList<PlantPhoto>>
    get() = _listPlantPhoto

private val _plantPhotoDisplay = MutableLiveData<PlantPhoto>()
val plantPhotoDisplay: LiveData<PlantPhoto>
    get() = _plantPhotoDisplay

fun displayPlantDetails(plantIndividual: PlantIndividual) {
    _navigateToSelectedPlant.value = plantIndividual
}

fun displayPlantDetailsComplete() {
    _navigateToSelectedPlant.value = null
}

fun retrievePlantList(plantIndividual: PlantIndividual) {
    val dataClassNum = plantIndividual.plantId
    viewModelScope.launch {
        mediaPlantList = context?.getExternalFilesDir("planio/dataclasses/$dataClassNum")
            ?.listFiles()?.sortedDescending()?.toMutableList() ?: mutableListOf()
    }
}

fun changeToPlantPhotos(plantList: MutableList<File>) {
        plantList.map {
            val file = FileInputStream(it)
            val inStream = ObjectInputStream(file)
            val item = inStream.readObject() as PlantPhoto
            newPhotoList.add(item)
        }

        _plantPhotoDisplay.value = newPhotoList.last()
        _listPlantPhoto.value = newPhotoList
}

}

Overview片段,我从其中从 RecyclerView 选择 plantIndividual 并导航到详细信息页面:

OverView Fragment from which I am selecting a plantIndividual from a RecyclerView and navigating to a details page:

viewModel.navigateToSelectedPlant.observe(viewLifecycleOwner, {
        if (null != it) {

            viewModel.retrievePlantList(it)
            viewModel.changeToPlantPhotos(viewModel.mediaPlantList)

            this.findNavController().navigate(
            CollectionOverviewFragmentDirections.
            actionCollectionOverviewFragmentToCollectionIndividualFragment(it))
        }
    })

细节片段:

class CollectionIndividualFragment: Fragment() {

private lateinit var binding: FragmentCollectionIndividualBinding

private val viewModel: CollectionOverviewViewModel by viewModels()

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = DataBindingUtil.inflate(inflater, R.layout.fragment_collection_individual, container, 
            false)
    binding.toCollectionOverview.setOnClickListener {
        this.findNavController().navigate(CollectionIndividualFragmentDirections.
        actionCollectionIndividualFragmentToCollectionOverviewFragment())
        viewModel.displayPlantDetailsComplete()
    }
    binding.viewModel = viewModel

    binding.lifecycleOwner = this

    binding.collectionIndividualRecyclerview.adapter = CollectionIndividualAdapter()

    binding.plantPhoto = viewModel.plantPhotoDisplay.value

    return binding.root
}

推荐答案

我想您是在设置绑定的viewModel之后设置了lifecycleOwner,因此,将viewModel设置为绑定后,它无法观察实时数据,因为此时,lifecycleOwner为null.我建议在设置绑定后进行设置

I guess you're setting the lifecycleOwner after setting the viewModel of your binding and as a result, after viewModel is set in binding, it cannot observe live data because the lifecycleOwner is null at that point. I suggest to set it after setting binding

binding = DataBindingUtil.inflate(inflater, R.layout.fragment_collection_individual, container, 
        false)
binding.lifecycleOwner = this

另外,不要忘了使用 by activityViewModels 而不是 byviewModels 在片段之间共享viewModel

Also don't forget to use by activityViewModels instead of by viewModels to share viewModel among your fragments

这篇关于绑定适配器实时数据值始终为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆