🐵
Flutterで無限スクロールしたい
課題
一覧ページでDBからユーザに紐づく全データを一括で取得しており、表示速度が低下していました。
やりたいこと
Xを例に出すと、特定のユーザの過去の投稿を遡るときに、数十件ずつをこまめに表示するアレです。
下までスクロールするとインジケータがぐるぐる回って、次の数十件が読み込まれます。
分割してAPIからデータを取り出すことによって、画面表示の速度を上げたいです。
改修
とりあえずAPI側でpageを引数に取ります。
これが分割の単位で、Flutterで取得する度に1からインクリメントされていきます。
def find_by_user(user_id: str, page: int, limit: int = 4):
sakes = # お酒一覧を取得(省略)
start_index = (page - 1) * limit
end_index = start_index + limit
return sakes[start_index:end_index]
ここからFlutterの処理
class {
int _currentPage = 1; // 現在のページ番号
bool _isLoading = false; // データ読み込み中かどうか
bool _hasMoreData = true; // 残りの表示データがあるか
final ScrollController _scrollController = ScrollController();
void initState() {
super.initState();
_scrollController.addListener(_onScroll); // スクロールイベントの監視
}
void dispose() {
_scrollController.removeListener(_onScroll); // スクロールイベントの監視を解除
_scrollController.dispose();
super.dispose();
}
void _onScroll() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_loadMoreData(); // 一番下までスクロールしたらデータを読み込む
}
}
Future<void> _loadMoreData() async {
if (_isLoading || !_hasMoreData) {
return; // 読み込み中またはデータがない場合は何もしない
}
setState(() {
_isLoading = true; // 読み込み中フラグを立てる
});
_currentPage++; // ページ番号を増やす
final newData = await sakeService.getSakes(_currentPage); // データを取得
if (newData.isEmpty) {
setState(() {
_hasMoreData = false; // データがなければ、もうデータがないフラグを立てる
});
}
setState(() {
_showItems.addAll(newData); // 取得したデータを表示しているリストに追加
_isLoading = false; // 読み込み中フラグを下ろす
});
}
Widget build(BuildContext context) {
// ~~省略~~
child: CupertinoScrollbar(
controller: _scrollController,
child: CustomScrollView(
controller: _scrollController,
slivers: <Widget> [] // 表示処理(省略)
),
),
}
}
Discussion