Как обновить состояние (состояние провайдера) внутри функции initState во Flutter? - PullRequest
0 голосов
/ 29 января 2020

Я хочу получить данные из API и установить эти данные в центральное состояние (провайдер) после создания экрана. (Аналогичный сценарий реакции useEfect function)

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 Ответ

1 голос
/ 29 января 2020

Я также новичок в 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();
  }
}
...