Наблюдать не вызывается с LiveData <PagedList> - PullRequest
0 голосов
/ 11 октября 2019

Я использую архитектурные компоненты PagedList, используя базу данных Room, и у меня возникают проблемы с возвратом результатов в метод наблюдения.

Вот мой Дао:

@Dao
interface WorkPackageStorageDao {

    @Query("SELECT * from workpackages where id = :id")
    fun getById(id: String): Workpackage

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(workpackage: Workpackage)

    @Query("Select * from workpackages WHERE id LIKE '%' || :searchString || '%' order by :orderBy")
    fun searchWorkpackages(searchString : String, orderBy : String) : DataSource.Factory<Int, Workpackage>

    @Query("SELECT * FROM workpackages")
    fun searchWorkPackgesTest() : List<Workpackage>

    @Query("Select * from workpackages WHERE id LIKE '%' || :searchString || '%' order by :orderBy")
    fun searchWorkPackgesTestQuery(searchString : String, orderBy : String) : List<Workpackage>

    @Query("DELETE from workpackages")
    fun deleteAll()

}

Мой репозиторий:

fun getAllWorkPackagesTestQuery() : List<Workpackage> {
    return workpackagesDao.searchWorkPackgesTestQuery("",SortedBy.WorkPackageNumber.type)
}

fun getAllWorkPackages() : DataSource.Factory<Int, Workpackage> {
    return getSortedAndSearchedWorkPackages("",
        SortedBy.WorkPackageNumber
    )
}

fun getSortedAndSearchedWorkPackages(searchString : String, sortBy: SortedBy) : DataSource.Factory<Int, Workpackage> {
    return workpackagesDao.searchWorkpackages(searchString,sortBy.type)
}

ВотМетод в моей модели представления:

suspend fun fetchWorkPackagesInitial(
    workWeek: Configurations.AppWeek,
    pagingLimit: Int
) {

    coroutineScope {
        withContext(Dispatchers.IO) {
            val factory: DataSource.Factory<Int, Workpackage> =
                workPackageRepository.getAllWorkPackages()

            val pagedListBuilder =
                LivePagedListBuilder<Int, Workpackage>(factory, pagingLimit)
            workPackagesList = pagedListBuilder.build() 
            val list = workPackageRepository.getAllWorkPackagesTestQuery() //27 Items returned, query is fine. 
        }

    }
}

Вот мой фрагмент:

    mainViewModel.week.observe(this, Observer {
        it ?: return@Observer

        launch { workPackagesViewModel.fetchWorkPackagesInitial(it, PAGING_LIMIT) }

    })

    //Observe never called.  
    workPackagesViewModel.workPackagesList?.observe(this, Observer { wpList ->
        wpList ?: return@Observer

        adapter = WorkPackagesRecyclerAdapter(this)
        adapter.submitList(wpList)
        binding.workPackagesRecyclerView.adapter = adapter
        adapter.notifyDataSetChanged()

    })

В качестве теста для моего запроса я реализовал:

val list = workPackageRepository.getAllWorkPackagesTestQuery() 

, который возвращает 27 элементов, так что запрос в порядке. Я неправильно настраиваю Dao, неправильный LivePagedListBuilder? Почему наблюдение не называется?

1 Ответ

1 голос
/ 11 октября 2019

Вы не получаете предметы, потому что это PagedList. Вам необходимо активировать загрузку, чтобы получить страницы.

Именно поэтому передача PagedList в PagedListAdapter через submitList в конечном итоге приведет к загрузке данных.

Вы также не делаетевам нужно вручную вызывать adapter.notifyDataSetChanged(), когда вы используете PagedListAdapter, потому что DiffUtil будет обрабатывать это внутренне.


Однако вам определенно следует извлечь DataSource.Factory и LivePagedListBuilderи PagedList в потоке пользовательского интерфейса (Dispatcher.MAIN), потому что многопоточность обрабатывается внутренней интеграцией Room в Paging lib. Наблюдение (и вызов getItem( на незагруженном элементе) вызовет загрузку, и загрузка будет выполняться асинхронно DataSource из коробки.



Способ использованияПейджинг выглядит так:

class MyViewModel(
    private val workPackageStorageDao: WorkPackageStorageDao
): ViewModel() {
    private val searchQuery: MutableLiveData<String> = MutableLiveData("")

    val workPackages: LiveData<PagedList<WorkPackage>> = Transformations.switchMap(searchQuery) { searchText ->
        val factory = workPackageStorageDao.searchWorkPackages(searchText, SortedBy.WorkPackageNumber)
        val pagedListBuilder = LivePagedListBuilder<Int, WorkPackage>(factory, pagingLimit)
        pagedListBuilder.build()
    }
}

Затем во фрагменте:

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

    // ... setup RecyclerView, etc

    viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java, viewModelFactory)
    viewModel.workPackages.observe(viewLifecycleOwner, Observer { pagedList ->
        adapter.submitList(pagedList)
    })
}

И в адаптере:

class MyAdapter: PagedListAdapter<WorkPackage, MyAdapter.ViewHolder>(WorkPackage.ITEM_CALLBACK) {
     override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
         val workPackage = getItem(position)
         if(workPackage != null) {
             holder.bind(workPackage)
         }
     }
}

Короче говоря, вам не нужны сопрограммыВот. Используйте библиотеку подкачки и LiveData, и она загрузится в правильные потоки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...