【问题标题】:Error could not find the correct provider above this widget错误无法在此小部件上方找到正确的提供程序
【发布时间】:2020-07-26 10:48:29
【问题描述】:

好的,我在使用 FutureProvider 时遇到了这个问题。

我已经在我的 MaterialApp 上方创建了一个 FutureProvider,所以应该可以识别它吧?

我的小部件树有点像这样:

MyApp >> Home >> CardVehicle

这是我创建对象 Provider 的 main.dart 代码:

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final Service service = Service();

  @override
  Widget build(BuildContext context) {
    return FutureProvider(
      create: (_) => service.fetchCarYear(),
      catchError: (_, error) => print(error),
      child: MaterialApp(
        title: 'KPM Demo',
        theme: ThemeData(
          primarySwatch: Colors.amber,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: Home(),
      ),
    );
  }
}

我的虚拟服务类:

class Service {
  Future<CarYear> fetchCarYear() async {
    CarYear carYear = CarYear();

    final response = await Future.delayed(
      Duration(milliseconds: 500),
      () => jsonEncode({
        "data": [
          {"year": "2020"},
          {"year": "2019"},
          {"year": "2018"}
        ]
      }),
    );

    carYear = CarYear.fromJson(jsonDecode(response));

    return carYear;
  }
}

这里是我放置 Provider 的地方:

class CardVehicle extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    CarYear carYear = Provider.of<CarYear>(context);

    return Container(
      padding: EdgeInsets.all(20),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(10),
        color: Colors.white,
      ),
      child: Column(
        children: <Widget>[
          DropdownButton(
            isExpanded: true,
            icon: Icon(Icons.keyboard_arrow_down),
            items: carYear.data
                .map((item) => DropdownMenuItem(child: Text(item.year)))
                .toList() ?? null,
            onChanged: null,
          ),
        ],
      ),
    );
  }
}

我是不是在某个地方犯了错误?请帮忙!

编辑:这是我的 CarYear 课程:

class CarYear {
  List<Data> data;

  CarYear({this.data});

  CarYear.fromJson(Map<String, dynamic> json) {
    if (json['data'] != null) {
      data = new List<Data>();
      json['data'].forEach((v) {
        data.add(new Data.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.data != null) {
      data['data'] = this.data.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Data {
  String year;

  Data({this.year});

  Data.fromJson(Map<String, dynamic> json) {
    year = json['year'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['year'] = this.year;
    return data;
  }
}

【问题讨论】:

  • 请提供 CarYear() 类的代码
  • 我已经添加了我的 CarYear 课程。它是从 json 生成到 dart 网站的。

标签: flutter flutter-provider


【解决方案1】:

Comming from the other question you posted.

您需要更改 futureProvidercatchError 以返回 CarYear 而不是 void。现在futureProvider 是Dynamic 类型,provider.of 不是在搜索dynamic 的提供者,而是CarYear 的提供者。

为避免这种情况,请让 catchError 返回一个空的 CarYear 或使其引发异常。

我希望这会有所帮助!

【讨论】:

    【解决方案2】:

    最好使用 ChangeNotifierProvider 来完成

    在您使用 MultiProvider 创建的主目录中

      @override
      Widget build(BuildContext context) {
        return MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (context) => Service()),
          ],
          child: MaterialApp(..)
        )
      }
    

    在服务类中我添加了extends ChangeNotifierenotifyListeners() 调用时,所有消费者都会更新

    class Service extends ChangeNotifier {
    
      // Variable set in Service
      CarYear _carYear = new CarYear();
      CarYear get carYear => _carYear;
    
      // init MultiProvider create() =>
      Service() {
        fetchCarYear();
      }
    
      Future<CarYear> fetchCarYear() async {
        _carYear = CarYear();
    
        final response = await Future.delayed(
          Duration(milliseconds: 500),
              () => jsonEncode({
            "data": [
              {"year": "2020"},
              {"year": "2019"},
              {"year": "2018"}
            ]
          }),
        );
    
        // update _carYear Variable
        _carYear = CarYear.fromJson(jsonDecode(response));
    
        // all Consumer get a refresh()
        notifyListeners();
      }
    
    }
    

    在 CardVehicle 中我放置了一个消费者,但 CarYear carYear = Provider.of&lt;Service&gt;(context).carYear 也在工作.. 但是使用 Provider.of 你会更新每个 notifyListeners() 整个小部件

    class CardVehicle extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
    
        return Container(
          padding: EdgeInsets.all(20),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            color: Colors.white,
          ),
          child: Column(
            children: <Widget>[
    
              // its better you do it here with a Consumer, because not the whole widget is updating
              new Consumer<Service>(
                  builder: (context, service, child) => new DropdownButton(
                      isExpanded: true,
                      icon: Icon(Icons.keyboard_arrow_down),
                      items: service.carYear.data
                          .map((item) => DropdownMenuItem(child: Text(item.year), value: item.year,))
                          .toList(),
                      onChanged: (value) {
                        print(value);
                      },
                    ),
                ),
            ],
          ),
        );
      }
    
    }
    

    【讨论】:

    • ChangeNotifier 就像我学习的第一个提供者。我也想使用其他提供商。不过感谢您的回答。
    【解决方案3】:

    仅适用于 FutureProvider 的示例

    MultiProvider(
      providers: [
        FutureProvider(create: (_) => Service().fetchCarYear()),
      ],
      child: MaterialApp(..)
    

    返回 CarYear 的服务类

    class Service {
    
      // Variable set in Service
      CarYear _carYear;
    
      Future<CarYear> fetchCarYear() async {
        _carYear = CarYear(data: new List());
    
        final response = await Future.delayed(
          Duration(milliseconds: 500),
              () => jsonEncode({
            "data": [
              {"year": "2020"},
              {"year": "2019"},
              {"year": "2018"}
            ]
          }),
        );
    
        // update _carYear Variable
        _carYear = CarYear.fromJson(jsonDecode(response));
    
        // all Consumer get a refresh()
        //notifyListeners();
        return _carYear;
      }
    
    }
    

    以及带有CarYear carYear = Provider.of&lt;CarYear&gt;(context); 的 CardVehicle

    class CardVehicle extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
    
        CarYear carYear = Provider.of<CarYear>(context);
    
        return Container(
          padding: EdgeInsets.all(20),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            color: Colors.white,
          ),
          child: Column(
            children: <Widget>[
              new DropdownButton(
                isExpanded: true,
                icon: Icon(Icons.keyboard_arrow_down),
                items: carYear != null ? carYear.data
                    .map((item) => DropdownMenuItem(child: Text(item.year), value: item.year,))
                    .toList() : null,
                onChanged: (value) {
                  print(value);
                },
              ),
            ],
          ),
        );
      }
    
    }
    

    【讨论】:

    • 只有 catchError,在你的 FutureProvider 中会出错
    猜你喜欢
    • 2021-11-11
    • 2020-08-04
    • 2020-09-18
    • 2019-11-29
    • 2021-11-18
    • 2021-01-13
    • 2021-07-22
    • 2020-12-01
    • 2020-05-19
    相关资源
    最近更新 更多