List.generate 在 null 上调用了 getter 'length'。接收者:空尝试调用:长度

时间:2021-02-03 10:59:18

标签: flutter

两个文件都有相同的问题 **getter 'length' 被调用为 null。 接收器:空 尝试调用:长度 ** 文件名 product.dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import './product_list.dart';
import '../../../api/api_conf.dart' as ApiBase;
import '../../../size_config.dart';
import './section_title.dart';

class PopularProducts extends StatefulWidget {
  @override
  _PopularProductsState createState() => _PopularProductsState();
}

class _PopularProductsState extends State<PopularProducts> {
  var url = ApiBase.baseURL + "menus.php";
  var menus;
  void initState() {
    super.initState();
    fetchData();
  }

  fetchData() async {
    var res = await http.get(url);
    menus = jsonDecode(res.body)["menu"];
    print(menus);
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: List.generate(menus.length, (index) {
        return Column(children: [
          Padding(
            padding: EdgeInsets.symmetric(
                horizontal: getProportionateScreenWidth(20),
                vertical: getProportionateScreenHeight(0)),
            child: SectionTitle(title: menus[index]["name"], press: () {}),
          ),
          SizedBox(height: getProportionateScreenWidth(20)),
          SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: ProductList(menuid: menus[index]["id"]),
          ),
        ]);
      }),
    );
  }
}

请检查 product.dart 文件的 res.body 打印

[{id: 1, name: Electronics }, {id: 2, name: New Cloths }, {id: 3, name: T-Shirt }, {id: 4, name: Pak }, {id: 5, name: Shoes } ]

下一个自定义小部件 product_list.dart 两个页面都有相同的问题

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:shop_app/components/product_card.dart';
import '../../../api/api_conf.dart' as ApiBase;
import 'package:http/http.dart' as http;

class ProductList extends StatefulWidget {
  final String menuid;
  const ProductList({Key key, @required this.menuid}) : super(key: key);
  @override
  _ProductListState createState() => _ProductListState();
}

class _ProductListState extends State<ProductList> {
  var products;
  void initState() {
    super.initState();
    var url = ApiBase.baseURL + "products.php?menu_id=" + widget.menuid;
    fetchdata(url);
  }

  fetchdata(url) async {
    var res = await http.get(url);
    products = jsonDecode(res.body);
    print(products);
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: List.generate(
        products.length,
        (index) {
          return ProductCard(product: products[index]);
        },
      ),
    );
  }
}

请检查 product_list.dart 文件的 res.body 打印

[{id: 1, name: IPhone 12, price: 300000, image: 1.jpg }, {id: 2, name: Nokia, price: 20000, image: 2.jpg }, {id: 3, name: OPPO, price: 50000, image: 3.jpg }, {id: 4, name: MI, price: 40000, image: 4.jpg }, {id: 5, name: Samsung, price: 34000, image: 5.jpg } ]

文件名 product_card.dart

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:shop_app/screens/details/details_screen.dart';
import '../api/api_conf.dart' as ApiBase;

import '../constants.dart';
import '../size_config.dart';

class ProductCard extends StatefulWidget {
  const ProductCard(
      {Key key,
      this.width = 140,
      this.aspectRetio = 1.02,
      @required this.product})
      : super(key: key);

  final double width, aspectRetio;
  final product;
  @override
  _ProductCardState createState() => _ProductCardState();

  static ProductCard fromJson(i) {}
}

class _ProductCardState extends State<ProductCard> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(left: getProportionateScreenWidth(20)),
      child: SizedBox(
        width: getProportionateScreenWidth(widget.width),
        child: GestureDetector(
          onTap: () => Navigator.pushNamed(
            context,
            DetailsScreen.routeName,
            arguments: ProductDetailsArguments(product: widget.product),
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              AspectRatio(
                aspectRatio: 1.02,
                child: Container(
                  padding: EdgeInsets.all(getProportionateScreenWidth(20)),
                  decoration: BoxDecoration(
                    color: kSecondaryColor.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(15),
                  ),
                  child: Hero(
                    tag: widget.product["id"].toString(),
                    child: FadeInImage(
                      image: NetworkImage(
                          ApiBase.productURL + widget.product["file_name"]),
                      placeholder: AssetImage('assets/images/1.jpg'),
                    ),
                  ),
                ),
              ),
              const SizedBox(height: 10),
              Text(
                widget.product["name"],
                style: TextStyle(color: Colors.black),
                maxLines: 2,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(
                    widget.product["price"].toString(),
                    style: TextStyle(
                      fontSize: getProportionateScreenWidth(18),
                      fontWeight: FontWeight.w600,
                      color: kPrimaryColor,
                    ),
                  ),
                  InkWell(
                    borderRadius: BorderRadius.circular(50),
                    onTap: () {},
                    child: Container(
                      padding: EdgeInsets.all(getProportionateScreenWidth(8)),
                      height: getProportionateScreenWidth(28),
                      width: getProportionateScreenWidth(28),
                      decoration: BoxDecoration(
                        color: widget.product["id"] == 1
                            ? kPrimaryColor.withOpacity(0.15)
                            : kSecondaryColor.withOpacity(0.1),
                        shape: BoxShape.circle,
                      ),
                      child: SvgPicture.asset(
                        "assets/icons/Heart Icon_2.svg",
                        color: widget.product["id"] == 1
                            ? Color(0xFFFF4848)
                            : Color(0xFFDBDEE4),
                      ),
                    ),
                  ),
                ],
              )
            ],
          ),
        ),
      ),
    );
  }
}

应用程序正常运行并在控制台上显示错误 * getter 'length' 被调用为 null。 接收器:空 尝试调用:长度 *

2 个答案:

答案 0 :(得分:0)

您的 fetchData 异步未在 initState 完成之前完成。因此,当 menus 方法运行时,build 仍然为空。

您可以改用 FutureBuilder

class PopularProducts extends StatelessWidget {
  var url = ApiBase.baseURL + "menus.php";

  Future<Map<String, dynamic>> fetchData() async {
    var res = await http.get(url);
    return jsonDecode(res.body)["menu"];
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Object>(
      future: fetchData(),
      builder: (context, snapshot) {
        switch (snapshot.connectionState) {
             case ConnectionState.waiting: return Text('Loading....');
             default:
               if (snapshot.hasError)
                  return Text('Error: ${snapshot.error}');
               else
              return Text('Result: ${snapshot.data}');
            }
      },
    );
  }
}

答案 1 :(得分:0)

问题是因为 Widget build 将首先被调用,并且您没有在第一页中初始化您的两个列表。

您应该按如下方式初始化您的列表:

var products = List<ProductsCard>();