Переменная связывания равна нулю. Как позволить наблюдателю в пользовательском интерфейсе подождать, пока запрошенные Livedata будут извлечены из базы данных? - PullRequest
2 голосов
/ 28 сентября 2019

Я пытаюсь получить данные из базы данных и затем связать их фрагментом с XML.Итак, у меня есть репозиторий, который передает данные из БД в ViewModel, а фрагмент пользовательского интерфейса наблюдает за результатами и затем связывает данные с XML.Но проблема в том, что приложение сокрушает, говоря, что данные равны нулю. Хотя я обнуляю нулевые данные в наблюдателе.

Я пытался выполнить запрос в фоновом потоке, который, кажется, работаетправильное возвращение данных (Фото).

Я думаю, проблема в том, что запрос занимает время, а наблюдатель во фрагменте не ожидает его выполнения.Таким образом, запрос в порядке, и я следую в точности по образцам 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>

_ фрагмент_фото.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)

1 Ответ

1 голос
/ 28 сентября 2019

Да, ваше предположение с «требуется время» правильно.Макет хочет нарисовать что-то, как только его привязка и в это время photo еще не загружен.Вы можете обработать нулевое значение в StringUtils.byUser() или добавить нулевую проверку в макете, как здесь: Привязка данных: установить свойство, если оно не равно нулю

...