簡體   English   中英

如何修復android架構組件分頁onItemAtEndLoaded進入循環?

[英]How to fix android architecture components paging onItemAtEndLoaded get in loop?

我正在嘗試練習android架構組件分頁

帶有 Room、MVVM 和 LiveData 的本地 + 遠程數據源

當我第一次滾動列表(獲取遠程數據)時,它通過 PagedList.BoundaryCallback 中的onItemAtEndLoaded進入循環,但下次打開活動時它會平滑滾動(獲取本地數據)

這是我的GitHub的鏈接在這里

誰能幫我看看如何解決它,謝謝!

活動

class PagingActivity : AppCompatActivity() {

    lateinit var viewModel: PagingViewModel
    lateinit var adapter: PagingAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_paging)

        val factory = PagingViewModelFactory(PagingRepository(), application)
        viewModel = ViewModelProviders.of(this,factory).get(PagingViewModel::class.java)
        adapter = PagingAdapter()
        recyclerView.adapter = adapter

        viewModel.pagedListLiveData.observe(this, Observer {

            adapter.submitList(it)

        })
    }
}

視圖模型

class PagingViewModel(repository: PagingRepository, application: Application) :
    AndroidViewModel(application) {

    val pagedListLiveData = repository.getDataItem(application)
}

存儲庫

class PagingRepository : PagingRepositoryCallback {

    private lateinit var localDataSource: DataSource.Factory<Int, DataItem>

    override fun getDataItem(application: Application): LiveData<PagedList<DataItem>> {

        val pagedListLiveData: LiveData<PagedList<DataItem>> by lazy {

            localDataSource = DataItemDbHelper(application).getRoomDataItemDao().getAllDataItem()

            val config = PagedList.Config.Builder()
                .setPageSize(25)
                .setEnablePlaceholders(false)
                .build()

            LivePagedListBuilder(localDataSource, config)
                .setBoundaryCallback(PagingBoundaryCallback(application))
                .build()
        }

        return pagedListLiveData
    }
}

interface PagingRepositoryCallback {
    fun getDataItem(application: Application): LiveData<PagedList<DataItem>>
}

邊界回調

class PagingBoundaryCallback(context: Context) :
    PagedList.BoundaryCallback<DataItem>() {

    private var page = 2

    private val api = AllPlayerApi.api

    private val dao = DataItemDbHelper(context).getRoomDataItemDao()

    override fun onZeroItemsLoaded() {
        super.onZeroItemsLoaded()

        api.getAllPlayer().enqueue(createWebserviceCallback())
    }

    override fun onItemAtEndLoaded(itemAtEnd: DataItem) {
        super.onItemAtEndLoaded(itemAtEnd)
        api.getAllPlayer(page).clone().enqueue(createWebserviceCallback())
    }

    private fun createWebserviceCallback(): Callback<AllPlayerData> {

        return object : Callback<AllPlayerData> {
            override fun onFailure(call: Call<AllPlayerData>?, t: Throwable?) {
                Log.d("Huang", " get player fail ")
            }

            override fun onResponse(call: Call<AllPlayerData>?, response: Response<AllPlayerData>) {

                Log.d("Huang", " onResponse " + page)

                response.body()!!.data!!.forEach {
                    it.imageUrl = "https://pdc.princeton.edu/sites/pdc/files/events/new-nba-logo-1.png"
                }

                insertItemsIntoDb(response)
                page++
            }
        }
    }

    private fun insertItemsIntoDb(response: Response<AllPlayerData>) {

        GlobalScope.launch {

            response.body()!!.data!!.forEach {

                dao.insert(it)
            }
        }
    }
}

邏輯為,如果onItemAtEndLoaded得到相同的itemAtEnd ,則什么都不做。

var lastItemAtEnd:DataItem? = null
override fun onItemAtEndLoaded(itemAtEnd: DataItem) {
    lastItemAtEnd?.timestamp?.apply{
        if(itemAtEnd.timestamp==this){
            return;
        }
    }
    super.onItemAtEndLoaded(itemAtEnd)
    api.getAllPlayer(page).clone().enqueue(createWebserviceCallback())
}

由於您的頁面大小為 25,因此頁面列表配置應將setInitialLoadSizeHint 設置為 25,以避免循環/不必要地調用onItemAtEndLoaded方法

val config = PagedList.Config.Builder()
                .setPageSize(25)
                .setInitialLoadSizeHint(25) //same as your page size
                .setEnablePlaceholders(false)
                .build()

我知道這已經很長時間了,但我只是發布解決方案以備不時之需。
您應該為您的適配器注冊一個觀察者並監聽onItemRangeInserted事件,如果項目范圍的起始位置為零,只需將適配器滾動到零位置,這將使您的RecyclerView在第一次加載時保持在零位置,順便說一下,您應該設置setPrefetchDistance值小於setInitialLoadSizeHint 這是適配器觀察者的 Java 代碼

adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            if(positionStart == 0)
                recyclerView.scrollToPosition(positionStart);
        }
    });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM