CSV 数据未显示在我的 Flutter 应用程序屏幕上

问题描述 投票:0回答:1

我正在尝试使用 CSV 数据集在 Flutter 中构建 Myntra 时尚应用程序。

这是我的代码:

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;
// ignore: unused_import
import 'product.dart';

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Product> _products = [];
  List<Product> _filteredProducts = [];
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    _loadCsvData();
  }

  Future<void> _loadCsvData() async {
    try {
      final csvString =
          await rootBundle.loadString('assets/myntra_fashion6.csv');
      List<List<dynamic>> csvTable = CsvToListConverter().convert(csvString);

      if (csvTable.isNotEmpty) {
        print('CSV Table Headers: ${csvTable[0]}');
      }

      List<Product> products = [];
      for (var i = 1; i < csvTable.length; i++) {
        print('CSV Row $i: ${csvTable[i]}');
        products.add(Product.fromCsv(csvTable[i]));
      }

      setState(() {
        _products = products;
        _filteredProducts = products;
        _isLoading = false;
      });
    } catch (e) {
      print("Error loading CSV data: $e");
    }
  }

  void _filterProducts(String query) {
    List<Product> filtered = _products.where((product) {
      return product.brandName.toLowerCase().contains(query.toLowerCase()) ||
          product.description.toLowerCase().contains(query.toLowerCase()) ||
          product.category.toLowerCase().contains(query.toLowerCase());
    }).toList();

    setState(() {
      _filteredProducts = filtered;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Myntra Fashion'),
        bottom: PreferredSize(
          preferredSize: Size.fromHeight(kToolbarHeight),
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              onChanged: (value) {
                _filterProducts(value);
              },
              decoration: InputDecoration(
                hintText: 'Search...',
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(8.0),
                  borderSide: BorderSide.none,
                ),
                filled: true,
                contentPadding: EdgeInsets.all(16.0),
                fillColor: Colors.white,
              ),
            ),
          ),
        ),
      ),
      body: _isLoading
          ? Center(child: CircularProgressIndicator())
          : ListView.builder(
              itemCount: _filteredProducts.length,
              itemBuilder: (context, index) {
                return ProductCard(product: _filteredProducts[index]);
              },
            ),
    );
  }
}

class ProductCard extends StatelessWidget {
  final Product product;

  ProductCard({required this.product});

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.all(8.0),
      child: ListTile(
        leading: Image.network(product.url,
            width: 50, height: 50, fit: BoxFit.cover),
        title: Text(product.brandName),
        subtitle: Text(product.description),
        trailing: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('₹${product.discountPrice.toStringAsFixed(2)}',
                style: TextStyle(fontWeight: FontWeight.bold)),
            Text('₹${product.originalPrice.toStringAsFixed(2)}',
                style: TextStyle(decoration: TextDecoration.lineThrough)),
          ],
        ),
      ),
    );
  }
}

我尝试了几个调试步骤,但屏幕仍然卡在圆形加载指示器处。这是产品型号:

class Product {
  final String url;
  final int productId;
  final String brandName;
  final String category;
  final String individualCategory;
  final String categoryByGender;
  final String description;
  final double discountPrice;
  final double originalPrice;
  final int discountOffer;
  final String sizeOption;
  final double ratings;
  final int reviews;
  final String standardizedSize;

  Product({
    required this.url,
    required this.productId,
    required this.brandName,
    required this.category,
    required this.individualCategory,
    required this.categoryByGender,
    required this.description,
    required this.discountPrice,
    required this.originalPrice,
    required this.discountOffer,
    required this.sizeOption,
    required this.ratings,
    required this.reviews,
    required this.standardizedSize,
  });

  factory Product.fromCsv(List<dynamic> csvRow) {
    return Product(
      url: csvRow[0],
      productId: int.parse(csvRow[1]),
      brandName: csvRow[2],
      category: csvRow[3],
      individualCategory: csvRow[4],
      categoryByGender: csvRow[5],
      description: csvRow[6],
      discountPrice: double.parse(csvRow[7]),
      originalPrice: double.parse(csvRow[8]),
      discountOffer: int.parse(csvRow[9]),
      sizeOption: csvRow[10],
      ratings: double.parse(csvRow[11]),
      reviews: int.parse(csvRow[12]),
      standardizedSize: csvRow[13],
    );
  }
}

我应该怎么做才能在应用程序中正确显示 CSV 内容?

我尝试使用 print 语句调试代码,但收到此错误:

Error loading CSV data: RangeError (index): Index out of range: index should be less than 1: 1
flutter csv flutter-dependencies
1个回答
0
投票

从错误消息来看,可能是因为您正在尝试访问 Product 类中的 .fromCsv 方法中不存在的行元素。让我们看一下(假设

CsvToListConverter().convert(csvString);
不会抛出任何错误:

  • 如果 csvTable 为空或只有一个元素(您称之为“标题”),它不会迭代,并且会调用 setState 方法,用 0 个要显示的数据更新您的 UI
  • 当有 2 个或更多项目时,您尝试将列表中的一个元素(从索引 1 开始,因为已经采用 0)从其数据行解析为名为 Product 的类。为此,您尝试解析或获取给定行的特定索引,但此时您可能会收到错误。

我建议您在迭代中添加一个断点,并检查您当时正在评估的

csvTable[i]
是否具有正确解析类所需的所有值。

© www.soinside.com 2019 - 2024. All rights reserved.