两个文件都有相同的问题 **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。 接收器:空 尝试调用:长度 *
答案 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>();