Yasir Mehmood
Yasir Mehmood

Reputation: 296

List.generate The getter 'length' was called on null. Receiver: null Tried calling: length

both files have same problem **The getter 'length' was called on null. Receiver: null Tried calling: length ** file name 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"]),
          ),
        ]);
      }),
    );
  }
}

please check res.body print of product.dart file

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

next custom widget product_list.dart both page have same problem

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]);
        },
      ),
    );
  }
}

please check res.body print of product_list.dart file

[{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 } ]

file name 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),
                      ),
                    ),
                  ),
                ],
              )
            ],
          ),
        ),
      ),
    );
  }
}

application working and error showing on console *The getter 'length' was called on null. Receiver: null Tried calling: length *

Upvotes: 0

Views: 605

Answers (2)

John Joe
John Joe

Reputation: 12803

The problem is because Widget build will be called first and you are not initialize both of your list in the first page.

You should initialize your List as below:

var products = List<ProductsCard>();

Upvotes: 0

Thierry
Thierry

Reputation: 8393

Your fetchData is async does not finish before initState finishes. Hence, menus is still null when the build method runs.

You could use a FutureBuilder instead:

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}');
            }
      },
    );
  }
}

Upvotes: 1

Related Questions