Поставщик Flutter `notifyListeners ()` не обновляется после начальной загрузки

#flutter #dart #flutter-provider

#flutter #dart #поставщик flutter

Вопрос:

Я создаю простую CRUD-страницу в flutter. Прямо сейчас мой список загружается изначально, но когда я пытаюсь его обновить, он не создает виджет заново.

У меня есть класс, который отвечает за создание списка элементов, извлеченных из базы данных

 class PlanList extends StatefulWidget {
  PlanList({Key key}) : super(key: key);

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

class _PlanListState extends State<PlanList> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      Provider.of<PlansProvider>(context, listen: true).loadPlans();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Consumer<PlansProvider>(
      builder: (context, data, _) => ListView.builder(
        itemCount: data.items.length,
        itemBuilder: (BuildContext context, int index) {
          return Text(data.items[index].type);
        },
      ),
    );
  }
}
 

У меня также есть модель поставщика, которая отвечает за обновление списка.

 class PlansProvider extends ChangeNotifier {
  List<Payload> _plansList = [];
  var _test = "test";

  get test => _test;
  UnmodifiableListView<Payload> get items => UnmodifiableListView(_plansList);

  loadPlans() {
    Plans _resu<
    getPlans()
        .then((value) => _result = value)
        .then((value) => _plansList = _result.payload)
        .whenComplete(() => notifyListeners());
  }
}

Future<Plans> getPlans() async {
  final response = await http.get('http://10.0.2.2:8080/plans');

  if (response.statusCode == 200) {
    return Plans.fromJson(json.decode(response.body));
  } else {
    throw Exception(response.statusCode);
  }
}
 

и моя функция, которая вызывает функцию модели поставщика, когда я хочу перезагрузить элементы из базы данных

 class CreatePlansPage extends StatefulWidget {
  CreatePlansPage({Key key}) : super (key: key);

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

class _CreatePlansPageState extends State<CreatePlansPage> {
  var _name = '';

  _handleTap(String string){
    setState(() {
      _name = string;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('$_name'),
      ),
      body: ListView(
        children: [
          ListTile(
            leading: Icon(Icons.add),
            title: Text("Dinner"),
            onTap: _handleTap('Dinner'),
          ),
          ListTile(
            leading: Icon(Icons.add),
            title: Text("Dinner"),
            onTap: _handleTap('Dinner'),
          ),
          Center(
            child: RaisedButton(
                onPressed: (){
                  setState(() {
                    createPlans(_name);
                    Navigator.pop(context);
                  });
                }
            ),
          )
        ],
      ),
    );
  }
}

createPlans(String name) async {
  final http.Response response = await http.post(
    'http://10.0.2.2:8080/plans',
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    },
    body: jsonEncode(<String, String>{
      'type': name,
    }),
  );

  if (response.statusCode == 200) {
    PlansProvider().loadPlans();
  }

  if (response.statusCode != 200) {
    throw Exception('Failed!!!!');
  }
}
 

Кто-нибудь знает, почему это не работает? Я что-то упустил?

Ответ №1:

в вашей createPlans вызываемой вами функции PlansProvider().loadPlans(); , которая отличается от той, которая предоставляется при вызове Provider.of<PlansProvider>(context, listen: false).loadPlans();

 RaisedButton(
  onPressed: () async{
    try{
      final bool created = await createPlans(_name);
      if(created) Provider.of<PlansProvider>(context, listen: false).loadPlans();
      Navigator.pop(context);
    } catch(e){
      print('there was a en error'); //do somehting with the error
    }
  }
),

createPlans(String name) async {
  final http.Response response = await http.post(
    'http://10.0.2.2:8080/plans',
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    },
    body: jsonEncode(<String, String>{
      'type': name,
    }),
  );

  if (response.statusCode == 200) {
    return true; //or just return, somehting to tell you it worked
  }

  if (response.statusCode != 200) {
    throw Exception('Failed!!!!');
  }
}
 

Также в вашем initState измените значение listen на false, чтобы избежать запуска кода более одного раза

 WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  Provider.of<PlansProvider>(context, listen: false).loadPlans();
  // if you use true then everytime notifyListeners fires it will run this code, which is undesirable
});
 

Комментарии:

1. Это сработало. Спасибо, что нашли время ответить.