我正在制作一个待办事项列表应用程序,我想拥有一个精美的列表,其中任务按日期分组在标题下(类似于Splen-DO的内容)。我将Android Paging库(与RecyclerView一起)与Room(作为数据存储)一起使用。对于标题,我使用RecyclerView的视图类型,并将标题添加到列表中,我使用的是自定义数据源,该数据包包装了Room的数据源,而不是返回Task Object,它返回的对象可以是Task或标头。
它是这样的:
一切正常,直到我对数据库进行更改。物品无缘无故地在RecyclerView中移动,有些重复并且在RecyclerView的乞求中有一些空的占位符。到目前为止,我一直在尝试解决“乞讨时出现空的占位符”问题。
我已经检查了我的数据源,它返回正确的数据且没有偏移量。然后我检查了适配器。getItem()方法返回所有具有偏移量的项,并在开头返回一些空项。当我开始深入研究时,我发现它是由PagedStorage中的某些mLoadingNullCount引起的,我不知道它的用途,因为它没有文档。
列表可正常
使用列表可正常
使用在我对列表进行更改之后,列表顶部的
空占位符空占位符
列表错误(gif)
错误列表
请忽略一些变量和类名,我使用一些捷克语单词,以便它们不会与某些系统类混淆。
Ukol =任务
适配器:
数据源:
片段:UkolListAdapter.javaMyDatasource.javaUkolListFragment.java
如果您需要更多代码或解释,请发表评论,我会为您添加。
我发现了一个错误。从房间数据库中的数据源可能不会给你名单staritng,你要求的,但在那里就是了,在loadInitial()并为您提供的索引(其中返回列表开始)中int position的parametr onResult()。因此,我在上返回了错误的数据loadInitial()。因此,我添加了一些算法,用于计算实际返回的数据LoadInitial()。我没有解决问题。
在我的 Android 应用程序中,我在RecyclerView使用 Room 和 Paging 库中显示数据。
我的实现与AsyncPagedListDiffer 文档中的示例非常相似。
流程如下:
相应的Observer将更改传递给Adapter:
myLiveData.observe(viewLifecycleOwner, Observer {
myAdapter.submitList(it)
})
Run Code Online (Sandbox Code Playgroud)该AsyncPagedListDiffer计算差异并相应地更新列表
我的问题是第 3 步的性能下降。
即使我只在列表顶部插入一个项目,不同的项目也必须检查所有项目(这非常低效,尤其是对于较大的数据集),而简单的notifyItemInserted(0)调用就足够了。
有没有办法解决这种行为?
例如,我可以告诉它不必检查所有项目吗?或者任何其他解决方案?
我真的很感激任何建议。
我试图实现Android Paging library与ViewModel和Kotlin Coroutines
我有一个ViewModel实现CoroutineScope. 这取决于Repository:
class MovieListViewModel(
private val movieRepository: MovieRepository
) : ViewModel(), CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.IO
private lateinit var _movies: LiveData<PagedList<MovieBrief>>
val movies: LiveData<PagedList<MovieBrief>>
get() = _movies
init {
launch {
_movies = LivePagedListBuilder(movieRepository.getMovies(), DATABASE_PER_PAGE)
.setBoundaryCallback(movieRepository.movieBoundaryCallback)
.build()
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的Repository. 我注入BoundaryCallback与KodeinDependecy注射器。
class MovieRepositoryImpl(
private val movieDao: MovieDao, …Run Code Online (Sandbox Code Playgroud) android kotlin android-viewmodel kotlinx.coroutines android-paging
我正在使用分页库从服务器获取数据,我想在每 10 个项目后显示广告。因此,当用户向下滚动并获取新项目并将其添加到 PagedList 时。我希望加载和添加新广告,RecyclerView就像 Instagram 在提要中显示广告一样。因此,如果用户滚动到 200 个项目,将逐渐显示 20 个广告!!。我已经阅读了几个教程,但我还没有想出一个简单的方法来做到这一点。
这是我的适配器。
class RequestsPagedAdapter(
private val retryCallback: () -> Unit, private val from: From)
: PagedListAdapter<RequestsQuery.Request, RecyclerView.ViewHolder>(POST_COMPARATOR) {
private var networkState: NetworkState? = null
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (getItemViewType(position)) {
R.layout.z_request_item -> (holder as RequestViewHolder).bind(getItem(position)!!, from)
R.layout.network_state_item -> (holder as NetworkStateItemViewHolder).bindTo(networkState)
R.layout.ad_admob_banner -> (holder as AdMobViewHolder)
}
}
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>) {
if (payloads.isNotEmpty()) {
val …Run Code Online (Sandbox Code Playgroud) 我想使用分页库,我正在使用协程从网络调用中获取数据。我已经验证从服务器正确检索了数据,但是当我从该方法调用回调时,我loadInitial在观察到的 LiveData 上一无所获。我已经尝试“模拟”服务器(以避免使用协程)并将结果传递给 Fragment。
当我使用协程时,我首先在大小为 0 的观察者上得到结果,然后当网络调用完成并使用回调时,我什么也没得到。问题似乎是我配置协程的方式。
用于协程的调度程序是否有问题?
这是 DataSource 的完整示例。使用的 CoroutineScope 是 ViewModel 提供的。
internal class CharactersDataSource(
private val coroutineScope: CoroutineScope,
private val characterRepository: CharacterRepository
) : PositionalDataSource<Character>() {
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Character>) {
TODO()
}
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Character>) {
coroutineScope.launch {
val result = characterRepository.fetchCharacters(
params.requestedStartPosition,
params.requestedLoadSize
)
if (result is Output.Success) {
val value = result.value
// This next call should trigger data to be dispatched onto the LiveData
callback.onResult(value.results, …Run Code Online (Sandbox Code Playgroud) 我想通过loadInitial或loadafter 中的callback.onError(或 callback.onRetryableError)将错误异常传递给我的分页适配器,但总是收到崩溃。经过一些调试后,我在库源中找到了这个:

这实际上是我在崩溃跟踪中收到的信息。只是“待办事项”。依赖版本:
'androidx.paging:paging-runtime-ktx:2.1.1'
在生产中出现这种异常消息是否可以,或者我做错了什么?无论如何......问题:任何其他“内置”方式将加载错误传递给适配器?
android android-architecture-components android-paging android-paging-library
我在我的项目中使用了 Jetpack 的Paging 3库来处理数据分页。我有一个用例,当用户更改搜索请求中的某些内容(例如添加/删除一些过滤器)时,我必须调用 API 并根据新的搜索请求使用新数据重新填充我的列表。但是当我创建新Pager实例并将其传递给我的PagingDataAdapter适配器时,它会抛出:
java.lang.IllegalStateException: Collecting from multiple PagingData concurrently is an illegal operation.
Run Code Online (Sandbox Code Playgroud)
我的实现是这样的:
存储库
class Repository {
fun getDataStream(request: Request): Flow<PagingData<Response>> {
return Pager(
config = PagingConfig(
pageSize = 10,
initialLoadSize = 10,
prefetchDistance = 3
),
initialKey = 1,
pagingSourceFactory = {
DataPagingSource(
request = request,
repository = this
)
}
).flow
}
fun getData(page: Int, request: Request): Result<Response> {
return remoteDataSource.getData(page, request)
}
}
Run Code Online (Sandbox Code Playgroud)
数据分页源
class DataPagingSource(
private …Run Code Online (Sandbox Code Playgroud) 在这个示例项目中,我有一个 DAO,它在 FTS4 表上使用 Paging 2 来搜索它,使用用户提供的搜索表达式:
@Query("SELECT snippet(paragraphsFts) FROM paragraphs JOIN paragraphsFts "+
"ON paragraphs.id == paragraphsFts.rowid WHERE paragraphsFts.prose "+
"MATCH :search ORDER BY sequence")
abstract fun filtered(search: String): DataSource.Factory<Int, String>
Run Code Online (Sandbox Code Playgroud)
我有一个BookRepositoryfiltered()函数,它只是通过对 DAO 的调用,我有一个SearchViewModel将 the 转换DataSource.Factory为 a的函数LiveData:
class SearchViewModel(search: String, repo: BookRepository) : ViewModel() {
val paragraphs = repo.filtered(search).toLiveData(pageSize = 15)
}
Run Code Online (Sandbox Code Playgroud)
vm.paragraphs.observe(this.viewLifecycleOwner) {
adapter.submitList(it)
}
Run Code Online (Sandbox Code Playgroud)
只要用户没有输入语法错误的搜索表达式,这就可以正常工作。在这种情况下,Room 会抛出异常,我看不到在哪里可以捕获它。
2020-08-30 …Run Code Online (Sandbox Code Playgroud) 按照此处提供的说明,我已经能够成功实现新的 alpha07 版本的 Paging 3 库:https : //developer.android.com/topic/libraries/architecture/paging/v3-paged-data#guava-livedata
但是,现在我需要检查返回的列表是否为空以便向用户显示视图或文本,但我无法在其分页设计的流结构中附加任何检查。
目前,这是我onViewCreated在遵循他们的指南后在 Java 中使用我的代码的方式:
MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
Lifecycle lifecycle = lifecycleOwner.getLifecycle();
Pager<Integer, MyEntity> pager = new Pager<>(new PagingConfig(10), () -> viewModel.getMyPagingSource());
LiveData<PagingData<MyEntity>> pagingDataLiveData = PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager), lifecycle);
pagingDataLiveData.observe(lifecycleOwner, data -> adapter.submitData(lifecycle, data));
Run Code Online (Sandbox Code Playgroud)
我尝试.filter在我的datain上附加 a adapter.submitData(lifecycle, data),但null尽管列表为空,但它从未收到项目。
在这种情况下,如何检查提交给适配器的数据何时为空?我在他们的文档中找不到任何指针。
编辑:这是我找到的解决方案,在这里发布是因为所选的答案严格来说不是解决方案,也不是在 Java 中,而是引导我找到它的答案。
我有一个附加LoadStateListener我的转接器,监听时LoadType是REFRESH和LoadState的是NotLoading,再检查是否adapter.getItemCount是0。
LoadType对于这种情况,可能采用不同的方法更合适,但到目前为止,刷新对我来说是有效的,所以我选择了那个。
示例:
// …Run Code Online (Sandbox Code Playgroud) 我目前的问题是,LoadStateAdapter显示加载和错误状态的 my 不在 my 内居中recyclerview,它有一个 gridlayout 作为布局管理器。我在官方 android 开发者网站上没有找到任何关于此的信息,所以我在这里问:如何将我的LoadStateAdapter内部集中在我的 Recyclerview 中?
@AndroidEntryPoint
class ShopFragment : Fragment(R.layout.fragment_shop), ShopAdapter.OnItemClickListener {
private val shopViewModel: ShopViewModel by viewModels()
private val shopBinding: FragmentShopBinding by viewBinding()
@Inject lateinit var shopListAdapter: ShopAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bindObjects()
}
private fun bindObjects() {
shopBinding.adapter = shopListAdapter.withLoadStateFooter(ShopLoadAdapter(shopListAdapter::retry))
shopListAdapter.clickHandler(this)
}
override fun onDestroyView() {
requireView().findViewById<RecyclerView>(R.id.rv_shop).adapter = null
super.onDestroyView()
}
}
Run Code Online (Sandbox Code Playgroud)
@FragmentScoped
class ShopLoadAdapter(private val retry: () …Run Code Online (Sandbox Code Playgroud) android kotlin android-recyclerview android-paging android-paging-3
android ×10
android-paging ×10
kotlin ×3
android-architecture-components ×2
admob ×1
android-room ×1
java ×1