У меня есть следующая схема XML:
<layout ....>
<data>
<variable
name="viewModel"
type="com.example.myrecyclerview.CategoryListFragmentViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
...
...>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/category_recyclerview"
...
<!-- this line below, does not work very well -->
app:categoryListData="@{viewModel.retrieveCategories()}"
<!-- the line below works perfect
app:categoryListData="@{viewModel.categories}"
-->
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Как вы можете видеть, с помощью концепции Data Binding
я передаю ссылку на класс ViewModel
. Используя эту ссылку ViewModel
, я звоню retrieveCategories()
. Вот содержимое класса ViewModel
:
class CategoryListFragmentViewModel(private val repository: CategoryDataRepository): ViewModel() {
fun retrieveCategories() = repository.getCategories() // <--- but this does not work
//val categories= repository.getCategories() <--- this works
}
Как видите, список объектов данных предоставляется методом, определенным в классе Repository
. Обратите внимание, что getCategories()
обрабатывает все содержимое библиотеки подкачки Android (см. Ниже в конце этого вопроса).
Итак, и теперь я хочу перейти к моему вопросу: как вы можете прочитать из моих комментариев выше, когда у меня app:categoryListData="@{viewModel.categories}"
в моем макете XML, библиотека подкачки справляется со своей задачей очень хорошо (когда RecyclerView нужны данные, она предоставляет данные и уменьшает количество запросов к веб-сервису).
Но когда у меня есть app:categoryListData="@{viewModel.retrieveCategories()}"
, как упомянуто выше, внезапно количество запросов увеличивается, и приложение начинает делать запросы все время. Я не могу понять, почему, поскольку они имеют один и тот же тип - тип categories
совпадает с типом возврата retrieveCategories()
.
Для полноты изложения здесь приведены недостающие части реализации. :
class CategoryDataRepository(private val dataSource: MyRoomDatabase,
private val categoryRemoteDataSource: CategoryRemoteDataSource) {
fun getCategories() : LiveData<PagedList<Category>>{
val dataSourceFactory = dataSource.categoryDao().getCategories()
// CategoryBoundaryCallback class overrides onZeroItemsLoaded() & onItemAtEndLoaded so that each these methods are invoked, a request to the service is triggered
val boundaryCallback = CategoryBoundaryCallback(dataSource, categoryRemoteDataSource)
return LivePagedListBuilder(dataSourceFactory, DATABASE_PAGE_SIZE)
.setBoundaryCallback(boundaryCallback)
.build()
}
companion object {
private const val DATABASE_PAGE_SIZE = 10
}
}
И, наконец, пользовательский адаптер привязки:
@BindingAdapter("categoryListData")
fun bindRecyclerViewCategoryList(recyclerView: RecyclerView, data: PagedList<Category>?){
val adapter = recyclerView.adapter as CategoryListAdapter
adapter.submitList(data)
}
Возвращаясь к моему вопросу: почему DataBinding работает, когда я использую переменную объекта LiveData, но не работает, когда я использую метод, возвращающий тот же тип.