Flutter导航到新页面时抛出错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter导航到新页面时抛出错误相关的知识,希望对你有一定的参考价值。

我已经通过JSON数据创建了Gridview构建器,但是当我导航到新页面时,出现错误:在此SingleItemScreen窗口小部件上方找不到正确的提供程序

要解决,请:

  • 确保提供者是此SingleItemScreen小部件的祖先
  • 向提供者提供类型
  • 向消费者提供类型
  • 将类型提供给Provider.of()
  • 确保使用正确的context

我不确定这是哪里出了问题。

List<Product> productFromJson(String str) => List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));

String productToJson(List<Product> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Product 
  String productId;
  String sku;
  String itemName;
  String listPrice;
  String publishedPrice;
  String onsale;
  String stockQuantity;
  StockStatus stockStatus;
  String ratingCount;
  String averageRating;
  String totalSales;
  String imagePath;
  String category;

  Product(
    this.productId,
    this.sku,
    this.itemName,
    this.listPrice,
    this.publishedPrice,
    this.onsale,
    this.stockQuantity,
    this.stockStatus,
    this.ratingCount,
    this.averageRating,
    this.totalSales,
    this.imagePath,
    this.category,
  );

  factory Product.fromJson(Map<String, dynamic> json) => Product(
    productId: json["product_id"],
    sku: json["sku"],
    itemName: json["item_name"],
    listPrice: json["list_price"],
    publishedPrice: json["published_price"],
    onsale: json["onsale"],
    stockQuantity: json["stock_quantity"],
    stockStatus: stockStatusValues.map[json["stock_status"]],
    ratingCount: json["rating_count"],
    averageRating: json["average_rating"],
    totalSales: json["total_sales"],
    imagePath: json["image_path"],
    category: json["category"],
  );

  Map<String, dynamic> toJson() => 
    "product_id": productId,
    "sku": sku,
    "item_name": itemName,
    "list_price": listPrice,
    "published_price": publishedPrice,
    "onsale": onsale,
    "stock_quantity": stockQuantity,
    "stock_status": stockStatusValues.reverse[stockStatus],
    "rating_count": ratingCount,
    "average_rating": averageRating,
    "total_sales": totalSales,
    "image_path": imagePath,
    "category": category,
  ;


enum StockStatus  INSTOCK 

final stockStatusValues = EnumValues(
  "instock": StockStatus.INSTOCK
);

class EnumValues<T> 
  Map<String, T> map;
  Map<T, String> reverseMap;

  EnumValues(this.map);

  Map<T, String> get reverse 
    if (reverseMap == null) 
      reverseMap = map.map((k, v) => new MapEntry(v, k));
    
    return reverseMap;
  


Future<List<Product>> fetchPhotos(http.Client client) async 
  final response =
  await client.get('http://flutter.bizsupplier.in/product.php');
  return compute(parsePhotos, response.body);


Future<List<Product>> parsePhotos(String responseBody) async 
  final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
  return parsed.map<Product>((json) => Product.fromJson(json)).toList();

    class MyHomePage extends StatelessWidget 
      @override
      Widget build(BuildContext context) 
        return FutureBuilder<List<Product>>(
          future: fetchPhotos(http.Client()),
          builder: (context, snapshot) 
            if (snapshot.hasError) print(snapshot.error);
            if (snapshot.hasData) 
              return PhotosList(product: snapshot.data);
             else 
              return Center(child: CircularProgressIndicator());
            
          ,
        );
      
    

    class PhotosList extends StatelessWidget 
      final List<Product> product;

      PhotosList(Key key, this.product) : super(key: key);

      @override
      Widget build(BuildContext context) 
        return GridView.builder(
          shrinkWrap: true,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
          ),
          itemCount: product.length,
          itemBuilder: (context, index) 
            return Card(
              child: Column(
                children: <Widget>[
                  Container(
                    height: 150,
                    child: GestureDetector(
                      onTap: ()
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => SingleItemScreen(),
                              settings: RouteSettings(
                                arguments: product[index]
                              )
                            )

                        );
                      ,
                        child: Image.network(product[index].imagePath)),
                  ),
                  Expanded(
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        RaisedButton(
                          onPressed: () ,
                          child: Text('Buy Now'),
                          color: Colors.redAccent,
                        ),
                      ],
                    ),
                  )
                ],
              ),
            );
          ,
        );
      
    


    class SingleItemScreen extends StatelessWidget 
      final List<Product> product;
      SingleItemScreen(Key key, this.product) : super(key: key);

      @override
      Widget build(BuildContext context) 
        final Product product = Provider.of<Product>(context, listen: false);
        return Scaffold(
            appBar: AppBar(
              title: Text('Test PhP Navigation'),
              actions: <Widget>[
                new IconButton(
                    icon: Icon(
                      Icons.search,
                      color: Colors.white,
                    ),
                    onPressed: () ),
                new IconButton(
                    icon: Icon(
                      Icons.shopping_cart,
                      color: Colors.white,
                    ),
                    onPressed: () ),

              ],
            ),
            body: SingleChildScrollView(
              child: Column(
                children: <Widget>[
                  Container(
                    height: 300,
                    child: Image.network(product.imagePath),
                  ),
                  Container(
                    child: Text(product.productId),
                  ),
                ],
              ),
            ),
            bottomNavigationBar: Container(
              width: MediaQuery.of(context).size.width,
              height: 50.0,
              child: Row(
                mainAxisSize: MainAxisSize.max,
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  Flexible(
                    fit: FlexFit.tight,
                    flex: 1,
                    child: RaisedButton(
                      onPressed: () ,
                      color: Colors.grey,
                      child: Center(
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Icon(
                              Icons.list,
                              color: Colors.white,
                            ),
                            SizedBox(
                              width: 4.0,
                            ),
                            Text(
                              "SAVE",
                              style: TextStyle(color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                  Flexible(
                    flex: 2,
                    child: RaisedButton(
                      onPressed: (),
                      color: Colors.greenAccent,
                      child: Center(
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Icon(
                              Icons.card_travel,
                              color: Colors.white,
                            ),
                            SizedBox(
                              width: 4.0,
                            ),
                            Text(
                              "ADD TO BAG",
                              style: TextStyle(color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ));
      
    


答案

您可以在下面复制粘贴运行完整代码

步骤1:注释settings并使用SingleItemScreen(product: product[index])

MaterialPageRoute(
                            builder: (context) =>
                                SingleItemScreen(product: product[index]),
                            /*settings: RouteSettings(
                                  arguments: product[index]
                              )*/
                          ));

步骤2:修改SingleItemScreen以接受product

class SingleItemScreen extends StatelessWidget 
  final Product product;
  SingleItemScreen(Key key, this.product) : super(key: key);

步骤3:备注Provider

//final Product product = Provider.of<Product>(context, listen: false);  

工作演示

enter image description here

完整代码

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;

List<Product> productFromJson(String str) =>
    List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));

String productToJson(List<Product> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Product 
  String productId;
  String sku;
  String itemName;
  String listPrice;
  String publishedPrice;
  String onsale;
  String stockQuantity;
  StockStatus stockStatus;
  String ratingCount;
  String averageRating;
  String totalSales;
  String imagePath;
  String category;

  Product(
    this.productId,
    this.sku,
    this.itemName,
    this.listPrice,
    this.publishedPrice,
    this.onsale,
    this.stockQuantity,
    this.stockStatus,
    this.ratingCount,
    this.averageRating,
    this.totalSales,
    this.imagePath,
    this.category,
  );

  factory Product.fromJson(Map<String, dynamic> json) => Product(
        productId: json["product_id"],
        sku: json["sku"],
        itemName: json["item_name"],
        listPrice: json["list_price"],
        publishedPrice: json["published_price"],
        onsale: json["onsale"],
        stockQuantity: json["stock_quantity"],
        stockStatus: stockStatusValues.map[json["stock_status"]],
        ratingCount: json["rating_count"],
        averageRating: json["average_rating"],
        totalSales: json["total_sales"],
        imagePath: json["image_path"],
        category: json["category"],
      );

  Map<String, dynamic> toJson() => 
        "product_id": productId,
        "sku": sku,
        "item_name": itemName,
        "list_price": listPrice,
        "published_price": publishedPrice,
        "onsale": onsale,
        "stock_quantity": stockQuantity,
        "stock_status": stockStatusValues.reverse[stockStatus],
        "rating_count": ratingCount,
        "average_rating": averageRating,
        "total_sales": totalSales,
        "image_path": imagePath,
        "category": category,
      ;


enum StockStatus  INSTOCK 

final stockStatusValues = EnumValues("instock": StockStatus.INSTOCK);

class EnumValues<T> 
  Map<String, T> map;
  Map<T, String> reverseMap;

  EnumValues(this.map);

  Map<T, String> get reverse 
    if (reverseMap == null) 
      reverseMap = map.map((k, v) => new MapEntry(v, k));
    
    return reverseMap;
  


Future<List<Product>> fetchPhotos(http.Client client) async 
  final response =
      await client.get('http://flutter.bizsupplier.in/product.php');
  return compute(parsePhotos, response.body);


Future<List<Product>> parsePhotos(String responseBody) async 
  final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
  return parsed.map<Product>((json) => Product.fromJson(json)).toList();


class MyHomePage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return FutureBuilder<List<Product>>(
      future: fetchPhotos(http.Client()),
      builder: (context, snapshot) 
        if (snapshot.hasError) print(snapshot.error);
        if (snapshot.hasData) 
          return PhotosList(product: snapshot.data);
         else 
          return Center(child: CircularProgressIndicator());
        
      ,
    );
  


class PhotosList extends StatelessWidget 
  final List<Product> product;

  PhotosList(Key key, this.product) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return GridView.builder(
      shrinkWrap: true,
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
      ),
      itemCount: product.length,
      itemBuilder: (context, index) 
        return Card(
          child: Column(
            children: <Widget>[
              Container(
                height: 150,
                child: GestureDetector(
                    onTap: () 
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) =>
                                SingleItemScreen(product: product[index]),
                            /*settings: RouteSettings(
                                  arguments: product[index]
                              )*/
                          ));
                    ,
                    child: Image.network(product[index].imagePath)),
              ),
              Expanded(
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    RaisedButton(
                      onPressed: () ,
                      child: Text('Buy Now'),
                      color: Colors.redAccent,
                    ),
                  ],
                ),
              )
            ],
          ),
        );
      ,
    );
  


class SingleItemScreen extends StatelessWidget 
  final Product product;
  SingleItemScreen(Key key, this.product) : super(key: key);

  @override
  Widget build(BuildContext context) 
    //final Product product = Provider.of<Product>(context, listen: false);
    return Scaffold(
        appBar: AppBar(
          title: Text('Test PhP Navigation'),
          actions: <Widget>[
            new IconButton(
                icon: Icon(
                  Icons.search,
                  color: Colors.white,
                ),
                onPressed: () ),
            new IconButton(
                icon: Icon(
                  Icons.shopping_cart,
                  color: Colors.white,
                ),
                onPressed: () ),
          ],
        ),
        body: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Container(
                height: 300,
                child: Image.network(product.imagePath),
              ),
              Container(
                child: Text(product.productId),
              ),
            ],
          ),
        ),
        bottomNavigationBar: Container(
          width: MediaQuery.of(context).size.width,
          height: 50.0,
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              Flexible(
                fit: FlexFit.tight,
                flex: 1,
                child: RaisedButton(
                  onPressed: () ,
                  color: Colors.grey,
                  child: Center(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
            

以上是关于Flutter导航到新页面时抛出错误的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 在验证表单时抛出错误

Flutter 在运行 build 或 run 时抛出错误

Android Studio 在运行 Flutter App 时抛出异常

Gradle 在从网络下载工件时抛出错误.. 异常:Gradle 任务 assembleDebug 失败,退出代码为 1

Flutter:状态更改后如何导航到新页面?

Flutter Stripe 在展示付款单时抛出 StripeException