Flutterで非同期でListViewを使わずリストを表示させる。
状態管理はriverpod、state_notifier、freezedを使用。
まずXxxListPageクラスの上のuseEffect内のxlsp.getXxxList()によって、firestoreからリストを取得して、XxxListState.listに入れる。XxxListState.listが更新されると、下のuseEffect内が実行され、XxxListState.displayListに新たな値(List<Widget>)が入る。
すると、以下の部分が更新されてリストを表示できる。
children: <Widget>[
for (int i = 0; i < xxxListState.displayList.length; i++)
xxxListState.displayList[i],
Text('list'),
],
XxxListPageクラス
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:xxx/provider/patient_list_provider.dart';
class XxxListPage extends HookWidget {
@override
Widget build(BuildContext context) {
final xlsp = useProvider(xxxListStateProvider);
final xxxListState = useProvider(xxxListStateProvider.state);
useEffect(() {
// ownerIdが同じものをstateに入れる
Future.microtask(() => xlsp.getXxxList());
return () {};
}, []);
useEffect(() {
// List<Widget>のものを更新する
Future.microtask(() {
xlsp.addWidgetList(xxxListState.list);
});
return () {};
}, [xxxListState.list]);
return Scaffold(
appBar: AppBar(
title: Text('一覧'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
for (int i = 0; i < xxxListState.displayList.length; i++)
xxxListState.displayList[i],
],
),
),
),
);
}
}
モデルは以下の通り。
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart'; // *.freezed.dartで必要なのでimportしておく
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'patient_list.freezed.dart';
part 'patient_list.g.dart';
@freezed
abstract class XxxListState with _$XxxListState {
const factory XxxListState({
@Default([]) List<dynamic> list,
@Default([]) List<dynamic> displayList,
}) = _XxxListState;
factory XxxListState.fromJson(Map<String, dynamic> json) =>
_$XxxListStateFromJson(json);
}
プロバイダーは以下の通り。
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/all.dart';
import 'package:xxx/client/firestore.dart';
import 'package:xxx/entity/xxx_list.dart';
import 'package:xxx/provider/login_provider.dart';
import 'package:state_notifier/state_notifier.dart';
final xxxListStateProvider =
StateNotifierProvider((_) => XxxListStateProvider());
class XxxListStateProvider extends StateNotifier<XxxListState> {
XxxListStateProvider() : super(const XxxListState());
Reader read;
Future initState(reader) async {
read = reader;
}
void dispose() {}
void getXxxList() async {
final _list = await read(fireStoreProvider)
.getDocs('xxxs', read(loginStateProvider).state.uid);
// print(_list[1]["name"]);
state = state.copyWith(list: _list);
}
void addWidgetList(list) {
var resultList = List<Widget>();
list.forEach((val) {
resultList.add(Row(
children: [
Text(val["name"]),
],
));
});
state = state.copyWith(displayList: resultList);
}
}