提供者和消费者问题

Provider and consumer issue

我对 flutter 还很陌生,我正在尝试使用 provider 包提高我的状态管理技能。我在加载我的类别和通知听众何时显示我的类别小部件而不是我的 modalprogressHUD

时遇到了一些困难

这里是 MyApp class:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<LoginProvider>(
          create: (_) => LoginProvider(),
        ),
        ChangeNotifierProvider<CatergoryProvider>(
          create: (_) => CatergoryProvider(),
        ),
        ChangeNotifierProvider<RegistrationProvider>(
          create: (_) => RegistrationProvider(),
        ),
        ChangeNotifierProvider<QuestionProvider>(
          create: (_) => QuestionProvider(),
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        debugShowCheckedModeBanner: false,
        theme: ThemeData.dark().copyWith(
          primaryColor: Colors.teal,
        ),
        initialRoute: DashBoard.id,
        routes: {
          WelcomeScreen.id: (context) => WelcomeScreen(),
          DashBoard.id: (context) => DashBoard(),
          QuizzPage.id: (context) => QuizzPage()
        },
      ),
    );
  }
}

我的分类供应商class:

import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:quizz_app/models/catergory.dart';
import 'package:quizz_app/services/services.dart';

class CatergoryProvider with ChangeNotifier {
  List<Catergory> catergory;
  String errorMessage;
  bool loading = false;

  Future<bool> fetchCatergory() async {
    setLoading(true);

    await Service(url: "https://quizapp1234.herokuapp.com/kategori")
        .fetchCatergory()
        .then((data) {
      if (data.statusCode == 200) {
        print('success');
        Iterable l = json.decode(data.body);
        setCatergory(
            List<Catergory>.from(l.map((data) => Catergory.fromJson(data))));
        setLoading(false);
      } else {
        Map<String, dynamic> result = json.decode(data.body);
        setMessage(result['message']);
      }
    });
    return isList();
  }

  bool isLoading() {
    return loading;
  }

  void setLoading(value) {
    loading = value;
    notifyListeners();
  }

  void setCatergory(value) {
    catergory = value;
    notifyListeners();
  }

  void setMessage(value) {
    errorMessage = value;
    notifyListeners();
  }

  List<Catergory> getList() {
    return catergory;
  }

  String getMessage() {
    return errorMessage;
  }

  bool isList() {
    return catergory != null ? true : false;
  }
}

这里是我包装我想要通知消费者的内容:

  Consumer<CatergoryProvider>(
    builder: (context, catergory, child) {
      catergory.fetchCatergory();
      catergories = catergory.getList();
      return catergory.isLoading()
          ? ModalProgressHUD(
              opacity: 0,
              inAsyncCall:
                  Provider.of<CatergoryProvider>(context).isLoading(),
              child: Scaffold())
          : catergoryPage(catergories, context);
    },
  ),

我的调试控制台:

════════ Exception caught by foundation library ════════════════════════════════
setState() or markNeedsBuild() called during build.
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by foundation library ════════════════════════════════
setState() or markNeedsBuild() called during build.
════════════════════════════════════════════════════════════════════════════════

发生的异常:

Exception has occurred.
FlutterError (A CatergoryProvider was used after being disposed.
Once you have called dispose() on a CatergoryProvider, it can no longer be used.)

builder: 内的 Consumer 中调用 fetchCatergory,在 fetchCatergory 方法中调用调用 notifyListeners() 的函数,每次调用 notifyListeners() 时, builder: 被召回,导致无限循环

仅当 getList() returns 为 null 且 isLoading() 为 false

时才尝试换行 catergory.fetchCatergory()

代码:

Consumer<CatergoryProvider>(     
    builder: (context, catergory, child) {
        if(!catergory.isLoading() && catergory.getList() == null) {      
            catergory.fetchCatergory();
        }
        catergories = catergory.getList();
        return catergory.isLoading()
            ? ModalProgressHUD(
            opacity: 0,
        inAsyncCall:
            Provider.of<CatergoryProvider>(context).isLoading(),
            child: Scaffold())
        : 
        catergoryPage(catergories, context);
   },
),