我正在尝试从数据库中获取数据,然后将其以片段形式绑定(bind)到XML。
因此,我有了将数据从数据库发送到ViewModel的存储库,UI片段正在观察结果,然后将数据绑定(bind)到XML。
但是问题在于,即使我在观察者中使空数据无效,该应用程序还是在说数据为空。
我尝试了在后台线程上执行查询,似乎在返回数据(照片)时工作正常。
我认为问题在于查询需要花费时间,并且片段中的Observer不会等待查询完成。
因此,查询还可以,我可以完全按照Google的示例进行操作,但无法找出问题所在。
提前致谢。
_PhotoRepository
class PhotoRepository @Inject constructor(
private val photoDao: PhotoDoa
) {
fun loadPhotoById(photoId: Int): LiveData<Photo> {
// var photo: Photo? = null
// this is working and i am getting the photo object
// appExecutors.diskIO().execute {
photo = photoDao.getObjectPhotoById(photoId)
}
return photoDao.getPhotoById(photoId)
}
}
_PhotoViewModel
class PhotoViewModel @Inject constructor(private val photoRepository:
PhotoRepository) :
ViewModel() {
private var _photoId = MutableLiveData<Int>()
val photoId: LiveData<Int>
get() = _photoId
val photo: LiveData<Photo> = Transformations
.switchMap(_photoId) { id ->
photoRepository.loadPhotoById(id)
}
fun setId(photoId: Int) {
// if (_photoId.value == photoId){
// return
// }
_photoId.value = photoId
}
}
_PhotoFragment
class PhotoFragment : Fragment(), Injectable {
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
var binding by autoCleared<FragmentPhotoBinding>()
lateinit var photoViewModel: PhotoViewModel
var photo = Photo()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate<FragmentPhotoBinding>(
inflater,
R.layout.fragment_photo,
container,
false
)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val params = PhotoFragmentArgs.fromBundle(arguments!!)
photoViewModel = ViewModelProviders.of(
this,
viewModelFactory).get(PhotoViewModel::class.java)
photoViewModel.setId(params.photoId)
// photoViewModel.photo.removeObservers(viewLifecycleOwner)
photoViewModel.photo.observe(viewLifecycleOwner, Observer {
if (it != null) {
binding.photo = it
}
})
}
}
_ Doa类中的查询
@Query(" SELECT * FROM Photo WHERE id = :id")
abstract fun getPhotoById ( id: Int): LiveData<Photo>
_fragment_photo.xml
<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>
<import type="com.mustafa.pixabayapp.models.Photo"/>
<variable
name="photo"
type="Photo"/>
<import type="com.mustafa.pixabayapp.utils.StringUtils" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/photo_fragment_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:imageUrl="@{photo.webFormatURL}"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/colorTransparentDark"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/photo_fragment_tags"
style="@style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{StringUtils.getTags(photo.tags)}"
tools:text="TEST - TEST - TEST"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/photo_fragment_user_name"
style="@style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:text="@{StringUtils.byUser(photo.userName)}"
tools:text="By: Mustafa"/>
<TextView
android:id="@+id/photo_fragment_comments"
style="@style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginEnd="4dp"
android:drawableStart="@drawable/ic_comment"
android:text="@{StringUtils.getCommentsAsString(photo.commentsCount)}"
tools:text="2222"/>
<TextView
android:id="@+id/photo_fragment_favorites"
style="@style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_toStartOf="@id/photo_fragment_comments"
android:drawableStart="@drawable/ic_favorite"
android:text="@{StringUtils.getFavoritesAsString(photo.favoritesCount)}"
tools:text="2222"/>
<TextView
android:id="@+id/photo_fragment_likes"
style="@style/PixabayImageTextUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:layout_toStartOf="@id/photo_fragment_favorites"
android:drawableStart="@drawable/ic_like"
android:text="@{StringUtils.getLikesAsString(photo.likesCount)}"
tools:text="2222"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
</layout>
_错误消息:
java.lang.IllegalArgumentException:
Parameter specified as non-null is null:
method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter
userName at com.mustafa.pixabayapp.utils.StringUtils.byUser(Unknown
Source:2)at com.mustafa.pixabayapp.databinding.FragmentPhotoBindingImpl.
executeBindings(FragmentPhotoBindingImpl.java:138)
最佳答案
是的,您对“需要时间”的假设是正确的。布局希望在绑定(bind)后尽快绘制一些内容,但此时尚未加载photo
。
您可以处理StringUtils.byUser()
中的空值,也可以在布局中添加空检查,如下所示:Data binding: set property if it isn't null