Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/224.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何使用查看寻呼机2转到使用寻呼机3加载数据的位置?_Android_Android Viewpager2_Android Paging - Fatal编程技术网

Android 如何使用查看寻呼机2转到使用寻呼机3加载数据的位置?

Android 如何使用查看寻呼机2转到使用寻呼机3加载数据的位置?,android,android-viewpager2,android-paging,Android,Android Viewpager2,Android Paging,我使用ViewPager2显示从服务器获取的数据,并使用Paging3库保存到房间数据库。我的问题是,如何通过代码导航到特定的视图寻呼机项目?如果我使用viewPager.setCurrentItem(position,false),那么这不起作用。例如,如果在左/右滑动时动态加载总共3000个项目,如何将位置设置为1000,然后从那里开始在两个方向上导航/加载数据?我不能让它工作 注意:在下面的DogPagingMediator类中,我也尝试在刷新块中设置一些起始编号,而不是最新(最高)的编号

我使用ViewPager2显示从服务器获取的数据,并使用Paging3库保存到房间数据库。我的问题是,如何通过代码导航到特定的视图寻呼机项目?如果我使用viewPager.setCurrentItem(position,false),那么这不起作用。例如,如果在左/右滑动时动态加载总共3000个项目,如何将位置设置为1000,然后从那里开始在两个方向上导航/加载数据?我不能让它工作

注意:在下面的DogPagingMediator类中,我也尝试在刷新块中设置一些起始编号,而不是最新(最高)的编号,但在加载应用程序时,如果数据库中本地不存在编号较高的项目,则视图寻呼机将仅在此位置启动,否则,不管刷新中返回的页面是什么,它总是从编号最高的项开始(我假设dogDao.getDogs()以降序获取数据库中的所有项)

p.p.S:我之所以使用live data而不是flow,是因为flow在我刷卡时由于某种原因导致NullPointerException

包含视图寻呼机的片段中onCreateView的代码:

    lifecycleScope.launch {
        // Fetch the latest dog item from the network (data is sorted by descending)
        if (!browseDogsViewModel.latestDogIsFetched()) {
            browseDogsViewModel.setLatestDogNumber()
        }

        browseDogsViewModel.pagingDataStream.observe(viewLifecycleOwner) {
            adapter.submitData(viewLifecycleOwner.lifecycle, it)
        }
    }
从视图模型:

val pagingDataStream = repository.getAllDogsPagingData()

suspend fun setLatestDogNumber() {
    latestDogNumber = repository.getLatestDogNumber()
}
从存储库:

fun getAllDogsPagingData() = Pager(
    config = PagingConfig(pageSize = PAGE_SIZE),
    remoteMediator = dogPagingMediator,
    pagingSourceFactory = { dogDao.getDogs() }
).liveData
中介(与Google paging3 codelab示例类似,只是它按降序排序)::

@OptIn(ExperimentalPagingApi::class)
类DogPagingMediator@Inject构造函数(
专用val dogDatabase:dogDatabase,
二等兵val dogDao:dogDao,
私有val remoteKeysDao:remoteKeysDao,
私人val服务:DogService,
):RemoteMediator(){
覆盖挂起乐趣加载(加载类型:加载类型,状态:PagingState):结果{
试一试{
val page=何时(加载类型){
LoadType.REFRESH->{
val remoteKeys=getRemoteKeyClosestToCurrentPosition(状态)
remoteKeys?.nextKey?.plus(页面大小):浏览日志视图模型。最新的DogNumber
}
LoadType.PREPEND->{
val remoteKeys=getRemoteKeyForFirstItem(状态)
if(remoteKeys==null){
//LoadType是PREPEND,因此之前加载了一些数据,
//所以我们应该可以拿到遥控钥匙
//如果remoteKeys为null,那么我们是一个无效状态,我们有一个bug
抛出InvalidObjectException(“远程键和prevKey不应为null”)
}
//如果前一个键为null,则无法请求更多数据
remoteKeys.prevKey
?:返回MediatorResult.Success(endofPaginationReach=true)
remoteKeys.prevKey
}
LoadType.APPEND->{
val remoteKeys=getRemoteKeyForLastItem(状态)
if(remoteKeys?.nextKey==null){
抛出InvalidObjectException(“远程键对于$loadType不应为null”)
}
remoteKeys.nextKey
}
}
val dogs:MutableList=mutableListOf()
用于(从第i页到第i页-页面大小){
试一试{
val响应=service.geDogWithNumber(i)
dogs.add(从DTO转换为(响应))
}捕获(例如:HttpException){
//当请求狗超出范围时将为404
如果(例如代码()!=404){
投手
}
}
}
val endofpaginationreach=dogs.isEmpty()
dogDatabase.withTransaction{
val prevKey=
如果(页面==BrowseDogsViewModel.latestDogNumber)为空,则页面+页面大小
val nextKey=if(endofPaginationReach)null else页面-页面大小
val keys=dogs.map{
RemoteKey(dogNum=it.number,prevKey=prevKey,nextKey=nextKey)
}
remoteKeysDao.insertAll(键)
dogDao.insertAll(狗)
}
返回结果。成功(
EndofPaginationReach=EndofPaginationReach
)
}捕获(异常:IOException){
返回中介结果。错误(异常)
}捕获(异常:HttpException){
返回中介结果。错误(异常)
}
}
private suspend fun getRemoteKeyForLastItem(状态:PagingState):RemoteKeys{
//获取检索到的最后一个包含项的页面。
//从最后一页,获取最后一项
返回状态.pages.lastOrNull{it.data.isNotEmpty()}?.data?.lastOrNull()
?让{狗->
//获取检索到的最后一项的远程密钥
remoteKeysDao.remoteKeysDogNum(dog.number)
}
}
private suspend fun getRemoteKeyForFirstItem(状态:PagingState):RemoteKeys{
//获取检索到的第一个包含项的页面。
//从第一页中,获取第一项
返回state.pages.firstOrNull{it.data.isNotEmpty()}?.data?.firstOrNull()
?让{狗->
//获取检索到的第一个项目的远程密钥
remoteKeysDao.remoteKeysDogNum(dog.number)
}
}
私有挂起功能getRemoteKeyClosestToCurrentPosition(
状态:分页状态
):遥控钥匙{
//分页库正在尝试在定位点位置之后加载数据
//获取最靠近锚定位置的项目
返回状态.anchorPosition?.let{position->
state.closestItemToPosition(位置)?.number?.let{num->
remoteKeysDao.remoteKeysDogNum(num)
}
}
}
私人娱乐中心(狗)
@OptIn(ExperimentalPagingApi::class)
class DogPagingMediator @Inject constructor(
    private val dogDatabase: DogDatabase,
    private val dogDao: DogDao,
    private val remoteKeysDao: RemoteKeysDao,
    private val service: DogService,
) : RemoteMediator<Int, Dog>() {
    override suspend fun load(loadType: LoadType, state: PagingState<Int, Dog>): MediatorResult {
        try {
            val page = when (loadType) {
                LoadType.REFRESH -> {
                    val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
                    remoteKeys?.nextKey?.plus(PAGE_SIZE) ?: BrowseDogsViewModel.latestDogNumber
                }
                LoadType.PREPEND -> {
                    val remoteKeys = getRemoteKeyForFirstItem(state)
                    if (remoteKeys == null) {
                        // The LoadType is PREPEND so some data was loaded before,
                        // so we should have been able to get remote keys
                        // If the remoteKeys are null, then we're an invalid state and we have a bug
                        throw InvalidObjectException("Remote key and the prevKey should not be null")
                    }
                    // If the previous key is null, then we can't request more data
                    remoteKeys.prevKey
                        ?: return MediatorResult.Success(endOfPaginationReached = true)
                    remoteKeys.prevKey
                }
                LoadType.APPEND -> {
                    val remoteKeys = getRemoteKeyForLastItem(state)
                    if (remoteKeys?.nextKey == null) {
                        throw InvalidObjectException("Remote key should not be null for $loadType")
                    }
                    remoteKeys.nextKey
                }
            }

            val dogs: MutableList<Dog> = mutableListOf()
            for (i in page downTo page - PAGE_SIZE) {
                try {
                    val response = service.geDogWithNumber(i)
                    dogs.add(convertFromDto(response))
                } catch (ex: HttpException) {
                    // Will be 404 when requesting a dog out of range
                    if (ex.code() != 404) {
                    throw ex
                    }
                }
            }

            val endOfPaginationReached = dogs.isEmpty()

            dogDatabase.withTransaction {
                val prevKey =
                    if (page == BrowseDogsViewModel.latestDogNumber) null else page + PAGE_SIZE
                val nextKey = if (endOfPaginationReached) null else page - PAGE_SIZE
                val keys = dogs.map {
                    RemoteKeys(dogNum = it.number, prevKey = prevKey, nextKey = nextKey)
                }

                remoteKeysDao.insertAll(keys)
                dogDao.insertAll(dogs)
            }

            return MediatorResult.Success(
                endOfPaginationReached = endOfPaginationReached
            )
        } catch (exception: IOException) {
            return MediatorResult.Error(exception)
        } catch (exception: HttpException) {
            return MediatorResult.Error(exception)
        }
    }

    private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Dog>): RemoteKeys? {
        // Get the last page that was retrieved, that contained items.
        // From that last page, get the last item
        return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
            ?.let { dog->
                // Get the remote keys of the last item retrieved
                remoteKeysDao.remoteKeysDogNum(dog.number)
            }
    }

    private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Dog>): RemoteKeys? {
        // Get the first page that was retrieved, that contained items.
        // From that first page, get the first item
        return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
            ?.let { dog->
                // Get the remote keys of the first items retrieved
                remoteKeysDao.remoteKeysDogNum(dog.number)
            }
    }

    private suspend fun getRemoteKeyClosestToCurrentPosition(
        state: PagingState<Int, Dog>
    ): RemoteKeys? {
        // The paging library is trying to load data after the anchor position
        // Get the item closest to the anchor position
        return state.anchorPosition?.let { position ->
            state.closestItemToPosition(position)?.number?.let { num ->
                remoteKeysDao.remoteKeysDogNum(num)
            }
        }
    }

    private fun convertFromDto(dogDto: DogDto): Dog {
        return Dog(...)
    }
}
class DogPagingAdapter() :
    PagingDataAdapter<Dog, DogPagingAdapter.ViewPagerViewHolder>(DogDiffUtilCallback) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewPagerViewHolder {
        return ViewPagerViewHolder(
            ItemDogViewPagerBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: ViewPagerViewHolder, position: Int) {
        holder.bind(getItem(position))
    }

    inner class ViewPagerViewHolder(private val binding: ItemDogViewPagerBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(dog: Dog?) {
            binding.dog = dog
            binding.executePendingBindings()
        }
    }
}