Provider每次加载数据时显示CircularProgressIndicator

时间:2019-12-06 10:50:36

标签: flutter dart

我有一个小部件可以显示父级(ParentWd)和子级数据(ChildWd)。当我选择/按下一个父级时,将加载并显示子级数据。它可以工作,但是每次子级通过提供程序加载数据时,我都需要显示一个CircularProgressIndicator :

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider.value(
            value: Child(),
          ),
        ],
        child: MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: StartPage(),
        ));
  }
}

class StartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: Column(
          children: <Widget>[
            ParentWd(),//parent
            ChildWd(),//child
          ],
        ));
  }
}

class ParentWd extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(children: <Widget>[
      OutlineButton(
        child: Text('Parent 1'),
        shape: StadiumBorder(),
        onPressed: () async {
          await Provider.of<Child>(context, listen: false).getData(1);//load child data
        },
      ),
      OutlineButton(
        child: Text('Parent 2'),
        shape: StadiumBorder(),
        onPressed: () async {
          await Provider.of<Child>(context, listen: false).getData(2);/load child data
        },
      ),
    ]);
  }
}

class ChildWd extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: Provider.of<Child>(context, listen: false).getData(1),
      builder: (ctx, prevData) {
        if (prevData.connectionState == ConnectionState.waiting) {
          return Column(
            children: <Widget>[
              SizedBox(
                height: 150,
              ),
              Center(child: CircularProgressIndicator()),//data is shown but not the CircularProgressIndicator
            ],
          );
        } else {
          if (prevData.error == null) {
            return Consumer<Child>(
              builder: (ctx, data, child) => GridView(
                padding: EdgeInsets.all(2),
                scrollDirection: Axis.vertical,
                shrinkWrap: true,
                children: data.children
                    .map(
                      (c) => OutlineButton(
                        child: Text(c.name),
                        shape: StadiumBorder(),
                        onPressed: () {},
                      ),
                    )
                    .toList(),
                gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                  maxCrossAxisExtent: 80,
                  childAspectRatio: 3 / 2,
                  crossAxisSpacing: 5,
                  mainAxisSpacing: 10,
                ),
              ),
            );
          } else {
            return Text('Error');
          }
        }
      },
    );
  }
}

class Child with ChangeNotifier {
  List<ChildItem> _children = [];

  List<ChildItem> get children {
    return [..._children];
  }

  Future<void> getData(int idP) async {
 return Future.delayed(const Duration(seconds: 2), () {//simulate server get data with delay
      List<ChildItem> ch = [];
      ch.add(ChildItem(id: 1, name: 'Child 1', idParent: 1));
      ch.add(ChildItem(id: 2, name: 'Child 2', idParent: 1));
      ch.add(ChildItem(id: 3, name: 'Child 3', idParent: 2));

      _children = ch.where((c) => c.idParent == idP).toList();
      notifyListeners();
    });
  }
}

class ChildItem {
  final int id;
  final String name;
  final int idParent;

  ChildItem({
    @required this.id,
    @required this.name,
    @required this.idParent,
  });
}

github code 谢谢

1 个答案:

答案 0 :(得分:0)

已解决:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider.value(
            value: Child(),
          ),
        ],
        child: MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: StartPage(),
        ));
  }
}

class StartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: Column(
          children: <Widget>[
            ParentWd(), //parent
            ChildWd(), //child
          ],
        ));
  }
}

class ParentWd extends StatefulWidget {
  @override
  _ParentWdState createState() => _ParentWdState();
}

class _ParentWdState extends State<ParentWd> {
  var _isInit = false;

  @override
  void didChangeDependencies() {
    if (!_isInit) {
      Future.delayed(Duration.zero).then((_) {
        Provider.of<Child>(context, listen: false).changeIndex(1);
      });
      _isInit = true;
    }
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return Row(children: <Widget>[
      OutlineButton(
        child: Text('Parent 1'),
        shape: StadiumBorder(),
        onPressed: () async {
          Provider.of<Child>(context, listen: false).changeIndex(1);
        },
      ),
      OutlineButton(
        child: Text('Parent 2'),
        shape: StadiumBorder(),
        onPressed: () async {
          Provider.of<Child>(context, listen: false).changeIndex(2);
        },
      ),
    ]);
  }
}

class ChildWd extends StatefulWidget {
  @override
  _ChildWdState createState() => _ChildWdState();
}

class _ChildWdState extends State<ChildWd> {
  var _isInit = false;

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: Provider.of<Child>(context, listen: true).getData(),
      builder: (ctx, prevData) {
        if (prevData.connectionState == ConnectionState.waiting) {
          return Column(
            children: <Widget>[
              SizedBox(
                height: 150,
              ),
              Center(child: CircularProgressIndicator()),
            ],
          );
        } else {
          if (prevData.error == null) {
            return Consumer<Child>(
              builder: (ctx, data, child) {
                return GridView(
                  padding: EdgeInsets.all(2),
                  scrollDirection: Axis.vertical,
                  shrinkWrap: true,
                  children: data.children
                      .map(
                        (c) => OutlineButton(
                          child: Text(c.name),
                          shape: StadiumBorder(),
                          onPressed: () {},
                        ),
                      )
                      .toList(),
                  gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                    maxCrossAxisExtent: 80,
                    childAspectRatio: 3 / 2,
                    crossAxisSpacing: 5,
                    mainAxisSpacing: 10,
                  ),
                );
              },
            );
          } else {
            return Text('Error');
          }
        }
      },
    );
  }
}

class Child with ChangeNotifier {
  var _parentIdx = 0;
  List<ChildItem> _children = [];

  List<ChildItem> get children {
    return [..._children];
  }

  void changeIndex(int idx) {
    _parentIdx = idx;
    notifyListeners();
  }

  Future<void> getData() async {
    return Future.delayed(const Duration(seconds: 1), () {
      //simulate server get data with delay
      List<ChildItem> ch = [];
      ch.add(ChildItem(id: 1, name: 'Child 1', idParent: 1));
      ch.add(ChildItem(id: 2, name: 'Child 2', idParent: 1));
      ch.add(ChildItem(id: 3, name: 'Child 3', idParent: 2));

      _children = ch.where((c) => c.idParent == _parentIdx).toList();
      //  notifyListeners();
    });
  }
}

class ChildItem {
  final int id;
  final String name;
  final int idParent;

  ChildItem({
    @required this.id,
    @required this.name,
    @required this.idParent,
  });
}