如何在Flutter中更新initState函数内部的状态(提供者状态)?

时间:2020-01-29 06:09:11

标签: flutter flutter-provider

我想在创建屏幕后从API提取数据并将这些数据设置为中央状态(提供者)。(类似于react useEfect函数的场景)

class MyApp2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Counter>(
        child: MyHomePage(title: 'Flutter Demo Home Page'),
        create: (BuildContext context) => Counter());
  }
}
    class _MyHomePageState extends State<MyHomePage> {
  void _incrementCounter(dynamic count) {
    count.incrementCounter();
  }

  int fetchData() {
    //api request code
    return data; // return fetched data
  }

  @override
  Widget build(BuildContext context) {
    final count = Provider.of<Counter>(context);

    count.setCounter(fetchData());

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '${count.counter}',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _incrementCounter(count),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class Counter with ChangeNotifier{
  int counter= 0;

  void setCounter(int x){
    counter =x;
    notifyListeners();
  }

  void clearCounter(){
    counter =0;
    notifyListeners();
  }
  void incrementCounter(){
    counter++;
    notifyListeners();
  }
}

它抛出异常,并且不起作用。

setState() or markNeedsBuild() called during build. 

如果我删除notifyListeners()函数,则该应用程序将无任何异常运行,但是我要重建的小部件不会重建。

void setCounter(int x){
    counter =x;
   // notifyListeners();
  }

最好的方法是什么?

1 个答案:

答案 0 :(得分:1)

我也是Provider的新手。因此,这可能不是一个好的解决方案。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyApp2(),
    );
  }
}

class MyApp2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Counter>(
      child: MyHomePage(title: 'Flutter Demo Home Page'),
      create: (BuildContext context) => Counter(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({Key key, this.title}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Consumer<Counter>(
          builder: (context, counter, _) {
            if (counter.waiting)
              return CircularProgressIndicator();
            else
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'You have pushed the button this many times:',
                  ),
                  Consumer<Counter>(
                    builder: (context, counter, _) {
                      return Text(
                        '${counter.counter}',
                        style: Theme.of(context).textTheme.display1,
                      );
                    },
                  ),
                ],
              );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: Provider.of<Counter>(context).incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class Counter with ChangeNotifier {
  int _counter;
  bool _waiting;

  Counter(){
    _waiting = true;
    _fetchCounterFromApi();
  }


  Future<void>_fetchCounterFromApi() async{
    _counter = await Future<int>.delayed(Duration(seconds: 2),() => 4);//Do Api request;
    _waiting = false;
    notifyListeners();
  }

  int get counter => _counter;

  bool get waiting => _waiting;

  void incrementCounter() {
    _counter++;
    notifyListeners();
  }
}