我有一个类似聊天的活动,我使用带有PagedListAdaper的RecyclerView来加载一堆消息.我正在使用PositionalDataSource来加载数据.加载它的自我工作正常但是当我发送消息时,我使我的数据源无效并且列表被重新制作.我的问题是,当它这样做时它会闪烁:

我尝试添加setHasStableIds(true)并重写getItemId,它可以在一个简单的适配器上工作,但它似乎在这里不起作用.我似乎也无法将项添加到getCurrentList(),因为它不受支持.此外,我没有使用数据库,只是向服务器发出请求.
所以我的问题是,除了使数据源失效之外,还有更好的方法吗?有没有办法阻止列表在发送消息时闪烁?或者这个图书馆不适合我的聊天活动?
编辑:
我的差异回调
private val DIFF_CALLBACK: DiffCallback<MessageModel> = object : DiffCallback<MessageModel>() {
override fun areItemsTheSame(@NonNull oldMessage: MessageModel, @NonNull newMessage: MessageModel) =
oldMessage.id == newMessage.id
override fun areContentsTheSame(@NonNull oldMessage: MessageModel, @NonNull newMessage: MessageModel) =
oldMessage.equals(newMessage)
}
Run Code Online (Sandbox Code Playgroud)
Edit2我修复了它:
所以我设法通过使用PagedListAdapterHelper并在加载项目后设置它的列表来修复它:
private var mHelper: PagedListAdapterHelper<MessageModel>? = null
init {
mHelper = PagedListAdapterHelper(this, DIFF_CALLBACK)
setHasStableIds(true)
}
fun setList(pagedList: PagedList<MessageModel>) {
pagedList.addWeakCallback(pagedList.snapshot(), object:PagedList.Callback() {
override fun onChanged(position: Int, count: Int) {
}
override fun onInserted(position: Int, count: Int) {
mHelper?.setList(pagedList) …Run Code Online (Sandbox Code Playgroud) 我正在尝试实现我正在使用 Room 的分页,我花了很长时间才意识到这一切都为我完成了,但我需要做的是能够过滤搜索并对我的数据进行排序。我想暂时将其保留为 LiveData,以便稍后交换为 Flow。\n我使用此方法来过滤搜索和排序,并且效果非常好,
\n @SuppressLint("DefaultLocale")\n private fun searchAndFilterPokemon(): LiveData<List<PokemonWithTypesAndSpecies>> {\n return Transformations.switchMap(search) { search ->\n val allPokemon = repository.searchPokemonWithTypesAndSpecies(search)\n Transformations.switchMap(filters) { filters ->\n val pokemon = when {\n filters.isNullOrEmpty() -> allPokemon\n else -> {\n Transformations.switchMap(allPokemon) { pokemonList ->\n val filteredList = pokemonList.filter { pokemon ->\n pokemon.matches = 0\n val filter = filterTypes(pokemon, filters)\n filter\n }\n maybeSortList(filters, filteredList)\n }\n }\n }\n pokemon\n }\n }\n }\nRun Code Online (Sandbox Code Playgroud)\n这里有一些切换映射,第一个是响应搜索更新
\n var search: MutableLiveData<String> = getSearchState()\nRun Code Online (Sandbox Code Playgroud)\n第二个是响应过滤器更新
\n val filters: MutableLiveData<MutableSet<String>> …Run Code Online (Sandbox Code Playgroud) 我怎样才能获得我PagingData<Product>持有的当前物品数量?我找到的唯一解决方案是调用,shopListAdapter.itemCount但这总是返回 0。
我想做的是:获取我的 PagingAdapter 当前显示的项目数量,将该值提交给我的 shopViewModel,然后在另一个片段(DialogFragment)中使用该值。PagingData<Product>或者:从我的视图模型内部获取项目数量
这是我目前的方法
@AndroidEntryPoint
class ShopFragment : Fragment(R.layout.fragment_shop), ShopAdapter.OnItemClickListener {
private val shopViewModel: ShopViewModel by navGraphViewModels(R.id.nav_shop) { defaultViewModelProviderFactory }
private var _shopBinding: FragmentShopBinding? = null
private val shopBinding: FragmentShopBinding get() = _shopBinding!!
@Inject lateinit var shopListAdapter: ShopAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_shopBinding = FragmentShopBinding.inflate(inflater, container, false)
return shopBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
collectShopList()
}
private …Run Code Online (Sandbox Code Playgroud) 我有一个显示搜索项目列表的搜索片段。如果用户输入某些内容,我会将该字符串作为新的查询参数传递给 url,并使用 paging 3 库获取新列表。
第一个解决方案是:
//viewModel
lateinit var postListUrl: String
val postList: Flow<PagingData<Post>> = Pager(PagingConfig(pageSize = 20)) {
PostPagingSource(postRepository, postListUrl)
}.flow.cachedIn(viewModelScope)
//fragment
fun showPostList(url: String) {
postListAdapter.submitData(lifecycle, PagingData.empty())
viewModel.postListUrl = url
viewLifecycleOwner.lifecycleScope.launch {
viewModel.postList.collectLatest {
postListAdapter.submitData(it)
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过此解决方案,通过更改 url ( showPostList(newUrl),列表保持不变。也许在 viewModel 中使用缓存列表。
另一种解决方案是:使用showPostList(initUrl)in onViewCreatedof 片段,然后通过更改参数使用 blow 方法:
//fragment
fun changePostList(url: String) {
viewModel.postListUrl = url
postListAdapter.refresh()
}
Run Code Online (Sandbox Code Playgroud)
这项工作有效,但如果旧列表和新列表有共同的项目,新列表将显示在最后一个共同的可见项目上。例如,如果旧列表的第 5 个位置项与新列表的第 7 个位置项相同,则在列表更改以显示新列表后,它将从第 7 个位置开始,而不是第一个项目。
我在这里找到了另一个解决方案:
//viewModel
val postListUrlFlow = MutableStateFlow("") …Run Code Online (Sandbox Code Playgroud) 我正在使用 Jetpack Compose,以及 Paging 3 库和 Jetpack Navigation。我面临的问题是我有一个 LazyList,它使用分页库从远程源获取数据。
视图模型
fun getImages(): Flow<PagingData<ObjectImage>> = Pager(
PagingConfig(PAGE_SIZE, enablePlaceholders = false)
) { DataHome(RANDOM) }.flow.cachedIn(viewModelScope)
Run Code Online (Sandbox Code Playgroud)
主页视图
val images = viewModelHome.getImages().collectAsLazyPagingItems()
LazyColumn {
...
}
Run Code Online (Sandbox Code Playgroud)
现在发生的情况是,当我使用导航到另一个视图navHostController.navigate(),然后按返回返回到 HomeView 时...LazyColumn 会重置自身并开始再次从网络加载项目。
所以我被这个问题困扰了。我尝试在 viewModel 变量中手动缓存...虽然它有效,但它搞砸了 SwipeRefresh (停止显示刷新状态)
data.apply {
when {
// refresh
loadState.refresh is LoadState.Loading -> {
ItemLoading()
}
// reload
loadState.append is LoadState.Loading -> {...}
// refresh error
loadState.refresh is LoadState.Error -> {...}
// reload error
loadState.append is LoadState.Error -> {...}
} …Run Code Online (Sandbox Code Playgroud) android android-jetpack android-paging android-jetpack-navigation android-jetpack-compose
我有一个RecyclerView有PagedListAdapter.
当我把RecyclerView里面NestedScrollView的PagedList不能计算列表的末尾所以开始请求新数据的连续突发。
主要问题是我应该如何使用PagedListAdapterinside NestedScrollView?
实际上,我是Paging Library的新手.这是一种情况,我正在从我的ViewModel观察PagedList,即使新闻列表出现在UI上也总是返回零.
viewModel.getNews().observe(this, news -> {
swipeRefreshLayout.setRefreshing(false);
Timber.d("news size is %s",news.size());// **news size is 0**
adapter.submitList(news);
});
Run Code Online (Sandbox Code Playgroud)
我的DataSource是
public class NewsDataSource extends ItemKeyedDataSource<String, News> {
private MutableLiveData<Resource.Status> netStatusLive = new MutableLiveData<>();
/*Hide Logic for clean purpose*/
private List<News> localNewsList = new ArrayList<>();
public NewsDataSource( /*Hide Logic for clean purpose*/) {
/*Hide Logic for clean purpose*/
}
@Override
public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull LoadInitialCallback<News> callback) {
netStatusLive.postValue(Resource.Status.LOADING);
localNewsList.clear();
Disposable disposable = /*Hide Logic for …Run Code Online (Sandbox Code Playgroud) android android-architecture-components android-jetpack android-paging
我正在使用jetpack的2个组件:分页库和导航。
就我而言,我有2个片段:ListMoviesFragment和MovieDetailFragment
当我滚动一定距离并单击recyclerview的电影项目时,MovieDetailFragment被附加,并且ListMoviesFragment在后堆栈中。然后我按返回按钮,ListMoviesFragment从后退堆栈中恢复。
该点是滚动位置,并且ListMoviesFrament的项被重置,就像第一次附加到其活动一样。因此,如何保持recyclerview的状态以防止这种情况?
换句话说,如何使用FragmentTransaction以传统方式但以现代方式(导航)保留整个片段的状态,例如隐藏/显示片段
我的示例代码:
片段布局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="net.karaokestar.app.SplashFragment">
<TextView
android:id="@+id/singer_label"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Ca s?"
android:textColor="@android:color/white"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/btn_game_more"
android:layout_centerVertical="true"
android:background="@drawable/shape_label"
android:layout_marginTop="10dp"
android:layout_marginBottom="@dimen/header_margin_bottom_list"
android:textStyle="bold"
android:padding="@dimen/header_padding_size"
android:textAllCaps="true"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list_singers"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Run Code Online (Sandbox Code Playgroud)
片段Kotlin代码:
package net.karaokestar.app
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import androidx.paging.LivePagedListBuilder
import androidx.paging.PagedList
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_splash.*
import net.karaokestar.app.home.HomeSingersAdapter
import net.karaokestar.app.home.HomeSingersRepository
class SplashFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? …Run Code Online (Sandbox Code Playgroud) android android-recyclerview android-architecture-navigation android-paging
我尝试以正常方式添加标题(不同的视图类型,将数据计数增加 1 等),但分页列表滚动条跳转到列表底部。
从那以后,我遇到了 AsyncPagedListDiffer并试图实现它,但现在除了标题之外的所有项目都消失了。谁能看到我做错了什么?
class MerchantHistoryAdapter : PagedListAdapter<MerchantHistoryResponse.Transaction, BaseViewHolder>(MerchantHistoryDiffUtilCallback()) {
lateinit var listener: HistoryItemListAdapterListener
lateinit var headerListener: HistoryItemHeaderListAdapterListener
lateinit var networkStateListener: NetworkStateListAdapterListener
private var networkState: NetworkState = NetworkState.LOADING
val adapterCallback = AdapterListUpdateCallback(this)
val listUpdateCallback = object : ListUpdateCallback {
override fun onInserted(position: Int, count: Int) {
adapterCallback.onInserted(position + 1, count)
}
override fun onRemoved(position: Int, count: Int) {
adapterCallback.onRemoved(position + 1, count)
}
override fun onMoved(fromPosition: Int, toPosition: Int) {
adapterCallback.onMoved(fromPosition + 1, toPosition + 1)
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试按照Codelab使用房间数据库作为事实来源和 RemoteMediator 来实现 Jetpack paging 3 库。该应用程序查询 google books api,但由于某种原因,当我执行搜索时,它会多次调用同一页面。例如,当我在不滚动的情况下搜索 fire 时,我会在日志中看到以下内容:
D/BooksRepository: new search: fire
D/BooksRemoteMediator: title: fire, page: 0
I/okhttp.OkHttpClient: --> GET https://www.googleapis.com/books/v1/volumes?q=intitle%3Afire&key=AIzaSyBxHmT9nFCp9n2uOHkS3Gcq2OO3zbxaMrw&maxResults=40&startIndex=0
I/okhttp.OkHttpClient: <-- 200 https://www.googleapis.com/books/v1/volumes?q=intitle%3Afire&key=AIzaSyBxHmT9nFCp9n2uOHkS3Gcq2OO3zbxaMrw&maxResults=40&startIndex=0 (648ms, unknown-length body)
D/BooksRemoteMediator: title: fire, page: 1
I/okhttp.OkHttpClient: --> GET https://www.googleapis.com/books/v1/volumes?q=intitle%3Afire&key=AIzaSyBxHmT9nFCp9n2uOHkS3Gcq2OO3zbxaMrw&maxResults=40&startIndex=1
I/okhttp.OkHttpClient: <-- 200 https://www.googleapis.com/books/v1/volumes?q=intitle%3Afire&key=AIzaSyBxHmT9nFCp9n2uOHkS3Gcq2OO3zbxaMrw&maxResults=40&startIndex=1 (608ms, unknown-length body)
D/BooksRemoteMediator: title: fire, page: 0
I/okhttp.OkHttpClient: --> GET https://www.googleapis.com/books/v1/volumes?q=intitle%3Afire&key=AIzaSyBxHmT9nFCp9n2uOHkS3Gcq2OO3zbxaMrw&maxResults=40&startIndex=0
I/okhttp.OkHttpClient: <-- 200 https://www.googleapis.com/books/v1/volumes?q=intitle%3Afire&key=AIzaSyBxHmT9nFCp9n2uOHkS3Gcq2OO3zbxaMrw&maxResults=40&startIndex=0 (629ms, unknown-length body)
D/BooksRemoteMediator: title: fire, page: 1
I/okhttp.OkHttpClient: --> GET https://www.googleapis.com/books/v1/volumes?q=intitle%3Afire&key=AIzaSyBxHmT9nFCp9n2uOHkS3Gcq2OO3zbxaMrw&maxResults=40&startIndex=1
I/okhttp.OkHttpClient: <-- 200 https://www.googleapis.com/books/v1/volumes?q=intitle%3Afire&key=AIzaSyBxHmT9nFCp9n2uOHkS3Gcq2OO3zbxaMrw&maxResults=40&startIndex=1 (843ms, …Run Code Online (Sandbox Code Playgroud) android-paging ×10
android ×9
android-architecture-components ×2
android-architecture-navigation ×1
kotlin-flow ×1
mvvm ×1
paging ×1
sorting ×1