【Android】KotlinでRecyclerViewの無限スクロール
マイレビューは初期表示時、一度に全データをロードする処理だったが、 テスト的に大量データを登録したらロード時に時間がかかりこれはいかんと思い修正。。 対応策として、無限スクロールを採用した。
1. RecycleViewにスクロールイベントを追加
無限スクロールを実現するために、リストをスクロールし、末尾付近に差し掛かったら、データをロードする処理を追加。 まずはスクロールリスナーを追加する!今回はこちらを参考にさせて頂きました。
abstract class ScrollPageListener(layoutManager: LinearLayoutManager): RecyclerView.OnScrollListener() { private var mLayoutManager: LinearLayoutManager? = null private var mPage: Int = 0 private var mPreTotalCount: Int = 0 private var mIsLoading: Boolean = false private var visibleThreshold = 0 init { mLayoutManager = layoutManager } override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { super.onScrollStateChanged(recyclerView, newState) } override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) // ロードするときに走るのは無駄なので、先にreturnする if (dx == 0 && dy == 0) { return } val visibleItemCount: Int = recyclerView.childCount val totalItemCount: Int = mLayoutManager!!.itemCount // グリッドの表示個数 val firstVisibleItem: Int = mLayoutManager!!.findFirstVisibleItemPosition() if (mIsLoading) { if (totalItemCount > mPreTotalCount) { mIsLoading = false mPreTotalCount = totalItemCount } } if (!mIsLoading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) { mIsLoading = true load(++mPage) } } abstract fun load(page: Int) }
次にActivity側でRecycleViewのスクロールイベントにスクロールリスナーを設定する!
recycleView.addOnScrollListener(object: ScrollPageListener(reviewRecycleView.layoutManager as LinearLayoutManager) { override fun load(page: Int) { Log.d("scroll", "末尾だよ! $page") // ここでデータをロードする処理を追加! } })
2. 末尾を検知し、データをロードした後の処理
末尾を検知したらデータをロード!ロードしたら、RecycleViewのアダプター側でデータを追加する! ここでつまずいた。。Adapterの「notifyItemRangeInserted」を実行しても行が追加されなかった。 色々調べると、データを追加し、Adapterで「notifyItemRangeInserted」を実行した後、 RecycleViewの「recycleView.scrollToPosition」を実行しないと行が追加されないみたい🐶
Activity側の処理
// ロードしたデータをAdapterに追加する(selectedReviewList→ロードしたデータのリスト) reviewAdapter!!.addItem(selectedReviewList) // ロードしているデータの末尾までスクロール(これをやらないとスクロールしないとデータが表示されない!) recycleView.scrollToPosition(reviewRowList.size)
Adapter側の処理
override fun getItemCount(): Int { // ・・・ } @Override override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { // ・・・ } @Override override fun onBindViewHolder(holder: MyViewHolder, position: Int) { // ・・・ } /** * 行を追加する */ fun addItem(reviewList: ArrayList<Review>) { val fromIdx = this.itemCount for (review in reviewList) { val idx = this.reviewList.indexOf(review) if (idx == -1) { this.reviewList.add(review) } } // ここでデータを追加されたことを通知!(通知しないと追加したデータが表示されない!) this.notifyItemRangeInserted(fromIdx, reviewList.size) }
リストって色々と考慮しないといけないなー🐈
マイレビューも是非インストールしてみてください!
今回は以上!