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);
}

&nbsp;プロバイダーは以下の通り。

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);
 }
}


いいなと思ったら応援しよう!