将 Json 数据解析为现有的 Flutter 小部件

Posted

技术标签:

【中文标题】将 Json 数据解析为现有的 Flutter 小部件【英文标题】:Parse Json Data into Existing Flutter Widget 【发布时间】:2020-11-16 17:22:18 【问题描述】:

你好,我现在正在学习颤振,我正在尝试获取 json 数据并将其显示在轮播小部件上,下面是完整的代码,以便您了解发生了什么

import 'package:flutter/material.dart';
import 'package:mares/components/drawer.dart';
import 'package:carousel_pro/carousel_pro.dart';
import 'package:mares/components/homecards.dart';
import 'package:mares/pages/contactus.dart';
import 'package:mares/pages/profile.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Elaph Training',
      theme: ThemeData(fontFamily: 'Roboto'),
      home: MyHomePage(),
    );
  


class MyHomePage extends StatefulWidget 

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 


  Future<List> getSlides() async 
    final response = await http.get("http://igh-eg.com/mares/json/slides.php");
    return json.decode(response.body);
  

  @override
  Widget build(BuildContext context) 
    Widget imagecarousel = new Container(
      height: 200.0,
      child: new Carousel(
        boxFit: BoxFit.cover,
        images: [
          AssetImage('assets/slide1.jpg'),
          AssetImage('assets/slide2.jpg'),
          AssetImage('assets/slide3.jpg'),
        ],
        autoplay: true,
        animationCurve: Curves.fastOutSlowIn,
        animationDuration: Duration(milliseconds: 2000),
        dotSize: 5.0,
        dotColor: const Color.fromRGBO(234, 91, 12, 1),
      ),
    );

    return Scaffold(
      appBar: new AppBar(
        backgroundColor: const Color.fromRGBO(32, 102, 174, 1),
        title: Text('Elaph Training Center'),
        actions: <Widget>[
          new IconButton(icon: Icon(Icons.phone_in_talk, color: Colors.white,), onPressed: ()Navigator.of(context).push(new MaterialPageRoute(builder: (context) => new ContactUsPage()));),//search button
          new IconButton(icon: Icon(Icons.supervised_user_circle, color: Colors.white,), onPressed: ()Navigator.of(context).push(new MaterialPageRoute(builder: (context) => new Profilepage()));),//cart button
        ],
      ),
      //--the end of the app bar--//
      //---start of the drawer---//
      drawer: NavDrawer(),
      body: new ListView(
        children: <Widget>[
          new FutureBuilder<List>(
            future: getSlides(),
            builder: (context, snapshot) 
              if (snapshot.hasError) print(snapshot.error);

              return snapshot.hasData
                  ? new ItemList(
                list: snapshot.data,
              )
                  : new Center(
                child: new CircularProgressIndicator(),
              );
            ,
          ),
          imagecarousel,
          SizedBox(height: 10.0,),
          HomeCards(),
        ],
      ),
    );
  


class ItemList extends StatelessWidget 
  final List list;
  ItemList(this.list);

  @override
  Widget build(BuildContext context) 
    return new ListView.builder(
      itemCount: list == null ? 0 : list.length,
      itemBuilder: (context, i) 
        return new Container(
          padding: const EdgeInsets.all(10.0),
          child: new Card(

              child: new ListTile(
                title: new Text(list[i]['name']),
                leading: new Image.network("http://igh-eg.com/mares/img/$list[i]['photo']"),
                subtitle: new Text("Description : $list[i]['desc']"),
              ),
            ),
        );
      ,
    );
  

目前数据是代码在上面定义的 listitem 类中运行良好,但是我希望数据显示在如下所示的轮播部分上

  Widget imagecarousel = new Container(
      height: 200.0,
      child: new Carousel(
        boxFit: BoxFit.cover,
        images: [
          AssetImage('assets/slide1.jpg'),
          AssetImage('assets/slide2.jpg'),
          AssetImage('assets/slide3.jpg'),
        ],
        autoplay: true,
        animationCurve: Curves.fastOutSlowIn,
        animationDuration: Duration(milliseconds: 2000),
        dotSize: 5.0,
        dotColor: const Color.fromRGBO(234, 91, 12, 1),
      ),
    );

有什么帮助吗?我在网上搜索了很多,我看不到我错过了什么

【问题讨论】:

【参考方案1】:

我已经用carousel_slider: ^2.2.1 & cached_network_image: ^2.1.0+1 包实现了类似的代码。 你可以试试下面的代码:

class _HomeScreenState extends State<HomeScreen> 
  Future<List<Product>> carouselProducts;
  ...
  // method to fecth data from URL 
  Future<List<Product>> getSlides() async 
    return await apiController.carouselDataFetch();
  

  @override
  void initState() 
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) 
      carouselProducts = getSlides();
    );
  

构建方法中的小部件:

FutureBuilder<List<Product>>(
    future: carouselProducts,
    builder: (BuildContext cont, AsyncSnapshot snapshot) 
      if (snapshot.connectionState != ConnectionState.done) 
        return Center(child: CircularProgressIndicator());
      
      if (snapshot.connectionState == ConnectionState.none) 
        return Center(
            child: Text("Turn-On Mobile Data / WiFi Please!",));
      
      if (snapshot.hasError) 
        return Center(
            child: Text("Something went wrong!",));
      
      return CarouselSlider.builder(
        options: CarouselOptions(
          height: 250,
          autoPlay: true,
          enableInfiniteScroll: false,
          enlargeCenterPage: true,
          scrollDirection: Axis.horizontal,
          scrollPhysics: const BouncingScrollPhysics(),
          enlargeStrategy: CenterPageEnlargeStrategy.height,
          autoPlayCurve: Curves.fastLinearToSlowEaseIn,
        ),
        itemCount: snapshot.data.length,
        itemBuilder: (BuildContext context, int index) 
          Product prod = snapshot.data[index];
          return CachedNetworkImage(
            imageUrl: prod.productImage,
            fit: BoxFit.fill,
            useOldImageOnUrlChange: true,
            fadeInCurve: Curves.linearToEaseOut,
            placeholder: (context, url) => Center(
                child: CircularProgressIndicator()),
            errorWidget: (context, url, error) =>
                Icon(Icons.error),
          );
        ,
      );
    ,
  )

输出:

仅供参考: 根据您的 API 响应数据更改此示例代码。

【讨论】:

【参考方案2】:

谢谢大家,但我发现问题出在我使用的小部件版本上,所以我只是按照以下步骤操作

第 1 步:我将版本 (carousel_pro: ^0.0.13) 添加到 pubspec.yaml

第 2 步:创建以下 dart 文件

import 'package:carousel_pro/carousel_pro.dart';
import 'package:flutter/material.dart';

Widget CarouselSlider(items) => SizedBox(
  height: 200,
  child: Carousel(
    boxFit: BoxFit.cover,
    images: items,
    autoplay: true,
    animationCurve: Curves.fastOutSlowIn,
    animationDuration: Duration(milliseconds: 1500),
  ),
);

然后在main.dart里面初始化状态时使用http,get获取数据,如下

class _MyHomePageState extends State<MyHomePage> 

  var items = [];
  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    //get json data function//
    getSlides();
  

  Future<List> getSlides() async 
    final response = await http.get("http://igh-eg.com/mares/json/slides.php");
    var result = json.decode(response.body);
    result['data'].forEach((data)
      setState(() 
        items.add(NetworkImage("http://igh-eg.com/mares/img/$data['photo']"));
      );
    );
    print(json.decode(response.body));
    return json.decode(response.body);
  

  @override
  Widget build(BuildContext context) 

    return Scaffold(
      appBar: new AppBar(
        backgroundColor: const Color.fromRGBO(32, 102, 174, 1),
        title: Text('Elaph Training Center'),
        actions: <Widget>[
          new IconButton(icon: Icon(Icons.phone_in_talk, color: Colors.white,), onPressed: ()Navigator.of(context).push(new MaterialPageRoute(builder: (context) => new ContactUsPage()));),//search button
          new IconButton(icon: Icon(Icons.supervised_user_circle, color: Colors.white,), onPressed: ()Navigator.of(context).push(new MaterialPageRoute(builder: (context) => new Profilepage()));),//cart button
        ],
      ),
      //--the end of the app bar--//
      //---start of the drawer---//
      drawer: NavDrawer(),
      body: new ListView(
        children: <Widget>[
          CarouselSlider(items),
          SizedBox(height: 10.0,),
          HomeCards(),
        ],
      ),
    );
  

它像图表一样工作,如果您正在处理大量数据和图像,更好的方法是使用 pub.dev 网站上的 networkcachedimage 小部件

感谢大家,特别感谢@Sanket Vekariya 的帮助

【讨论】:

以上是关于将 Json 数据解析为现有的 Flutter 小部件的主要内容,如果未能解决你的问题,请参考以下文章

不可解析的父 POM,尽管 relativePath 设置为现有的父 pom.xml

Flutter -------- 解析JSON数据

使用Flutter + V8/JsCore开发小程序引擎(一)

Flutter DistanceMatrix JSON 无法正确解析

Flutter -- JSON解析

为现有的 django 模式重新创建数据库