Flutter:如何调用本地 JSON 数据并动态添加到标签栏?

Posted

技术标签:

【中文标题】Flutter:如何调用本地 JSON 数据并动态添加到标签栏?【英文标题】:Flutter : How to call Local JSON Data and added to Tabbar dinamically? 【发布时间】:2022-01-21 06:39:36 【问题描述】:

我希望通过使用 JSON 来缩短我的代码。请帮忙,如何将本地 JSON 生成到 Tabbar 中?以前我读过这个网站的帖子,但它调用 JSON API,而不是 LOCAL JSON。我还是不明白怎么称呼它

我想要这样的应用

我的 JSON 文件 (assets/product.json)

[

    "id": 1,
    "title": "NoteBook",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.",
    "image": "assets/img/notebook.jpg",
    "price": "Rp. 13.000.000"
,

    "id": 2,
    "title": "Printer",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.",
    "image": "assets/img/printer.jpg",
    "price": "Rp. 700.000"
,

    "id": 3,
    "title": "Mouse",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.",
    "image": "assets/img/standard-mouse.jpg",
    "price": "Rp. 1.100.000"
,

    "id": 4,
    "title": "Keyboard",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.",
    "image": "assets/img/rgb-keyboard.jpg",
    "price": "Rp. 2.100.000"
,

    "id": 5,
    "title": "Mouse Gaming",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.",
    "image": "assets/img/gaming-mouse.jpg",
    "price": "Rp. 500.000"
,

    "id": 6,
    "title": "Proccessor",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.",
    "image": "assets/img/procie.jpg",
    "price": "Rp. 6.000.000"
,

    "id": 7,
    "title": "Solid State Drive",
    "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.",
    "image": "assets/img/ssd.jpg",
    "price": "Rp. 2.100.000"

]

我的产品模型 (ProductModel.dart)

import 'dart:convert';

List<Product> ProductFromJson(String str) =>
    List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));

class Product 
  Product(
    this.id,
    this.title,
    this.image,
    this.description,
    this.price,
  );
  final int id;
  final String title;
  final String image;
  final String description;
  final String price;

  factory Product.fromJson(Map<String, dynamic> json) => Product(
        id: json["id"],
        title: json["title"],
        image: json["image"],
        description: json["description"],
        price: json["price"],
      );

  String getTitle() 
    return title;
  

  String getImage() 
    return image;
  

  String getDescription() 
    return description;
  

  String getPrice() 
    return price;
  

我的主页(MainPage.dart)

import 'package:flutter/material.dart';

class MainPage extends StatefulWidget 
  const MainPage(Key key) : super(key: key);

  @override
  State<MainPage> createState() => _MainPageState();


class _MainPageState extends State<MainPage>
    with SingleTickerProviderStateMixin 
  TabController myTabController;

  List<Widget> myTabs = [];
  List<Widget> myTabsContent = [];

  @override
  void initState() 
    super.initState();
    myTabController = TabController(vsync: this, length: myTabs.length);
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        titleSpacing: 10,
        title: Text("My Store"),
        bottom: TabBar(
          labelPadding: EdgeInsets.fromLTRB(20, 0, 20, 10),
          isScrollable: true,
          controller: myTabController,
          tabs: myTabs.toList(),
        ),
      ),
      body: TabBarView(
        controller: myTabController,
        children: myTabsContent.toList(),
      ),
    );
  

【问题讨论】:

【参考方案1】:

您可以尝试此方法从 json 加载产品并使用 FutureBuilder 加载内容并将其显示到您的标签:

    Future<List<Product>> _getProducts() async 
    // Load json from file system
    final dataString =
    await rootBundle.loadString('assets/product.json');
    // Decode to json
    final List<dynamic> json = jsonDecode(dataString);

    // Go through each post and convert json to Post object.
      final products = <Product>[];
      json.forEach((v) 
        products.add(Product.fromJson(v));
      );
      return products;
  

基于您的代码的示例(您需要更新代码以根据结果处理 myTabs 和 myTabsContent 的初始值):

import 'dart:convert';

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

class MainPage extends StatefulWidget 
  const MainPage(Key? key) : super(key: key);

  @override
  State<MainPage> createState() => _MainPageState();


class _MainPageState extends State<MainPage>
    with SingleTickerProviderStateMixin 
  late TabController myTabController;

  List<Widget> myTabs = const [
    Tab(icon: Icon(Icons.directions_car)),
    Tab(icon: Icon(Icons.directions_transit)),
    Tab(icon: Icon(Icons.directions_bike)),
  ];
  List<Widget> myTabsContent = [];

  Future<List<Product>> _getProducts() async 
    // Load json from file system
    final dataString = await rootBundle.loadString('assets/product.json');
    // Decode to json
    final List<dynamic> json = jsonDecode(dataString);

    // Go through each post and convert json to Post object.
    final products = <Product>[];
    json.forEach((v) 
      products.add(Product.fromJson(v));
    );
    return products;
  

  @override
  void initState() 
    super.initState();
    myTabController = TabController(vsync: this, length: myTabs.length);
  

  @override
  Widget build(BuildContext context) 
    return FutureBuilder(
        future: _getProducts(),
        builder: (context, AsyncSnapshot<List<Product>> snapshot) 
          if (snapshot.connectionState == ConnectionState.done) 
            return Scaffold(
              appBar: AppBar(
                titleSpacing: 10,
                title: const Text("My Store"),
                bottom: TabBar(
                  isScrollable: true,
                  controller: myTabController,
                  tabs: myTabs,
                ),
              ),
              body: TabBarView(controller: myTabController, children: [
                _buildItems(snapshot.data!.first),
                Icon(Icons.directions_transit),
                Icon(Icons.directions_bike),
              ]),
            );
           else 
            return const Icon(Icons.directions_car);
          
        );
  

  Widget _buildItems(Product product) 
    return Column(
      children: [
        Text(product.title),
        Text(product.price)
      ],
    );
  


//

List<Product> ProductFromJson(String str) =>
    List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));

class Product 
  Product(
    required this.id,
    required this.title,
    required this.image,
    required this.description,
    required this.price,
  );

  final int id;
  final String title;
  final String image;
  final String description;
  final String price;

  factory Product.fromJson(Map<String, dynamic> json) => Product(
        id: json["id"],
        title: json["title"],
        image: json["image"],
        description: json["description"],
        price: json["price"],
      );

  String getTitle() 
    return title;
  

  String getImage() 
    return image;
  

  String getDescription() 
    return description;
  

  String getPrice() 
    return price;
  

Here is result

【讨论】:

我收到错误消息_TypeError(类型'List'不是'Map'类型的子类型) 我刚刚更新,重试【参考方案2】:

这是我添加您的代码后的代码。但数据未显示:( Mr booykoquay

import 'dart:convert';

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

class MainPage extends StatefulWidget 
  const MainPage(Key key) : super(key: key);

  @override
  State<MainPage> createState() => _MainPageState();


class _MainPageState extends State<MainPage>
    with SingleTickerProviderStateMixin 
  TabController myTabController;

  List<Widget> myTabs = [];
  List<Widget> myTabsContent = [];

  Future<List<Product>> _getProducts() async 
    // Load json from file system
    final dataString = await rootBundle.loadString('assets/product.json');
    // Decode to json
    final List<dynamic> json = jsonDecode(dataString);

    // Go through each post and convert json to Post object.
    final products = <Product>[];
    json.forEach((v) 
      products.add(Product.fromJson(v));
    );
    return products;
  

  @override
  void initState() 
    super.initState();
    myTabController = TabController(vsync: this, length: myTabs.length);
  

  @override
  Widget build(BuildContext context) 
    return FutureBuilder(
        future: _getProducts(),
        builder: (context, _) 
          return Scaffold(
            appBar: AppBar(
              titleSpacing: 10,
              title: const Text("My Store"),
              bottom: TabBar(
                isScrollable: true,
                controller: myTabController,
                tabs: myTabs.toList(),
              ),
            ),
            body: TabBarView(
              controller: myTabController,
              children: myTabsContent.toList(),
            ),
          );
        );
  


//

List<Product> ProductFromJson(String str) =>
    List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));

class Product 
  Product(
    this.id,
    this.title,
    this.image,
    this.description,
    this.price,
  );
  final int id;
  final String title;
  final String image;
  final String description;
  final String price;

  factory Product.fromJson(Map<String, dynamic> json) => Product(
        id: json["id"],
        title: json["title"],
        image: json["image"],
        description: json["description"],
        price: json["price"],
      );

  String getTitle() 
    return title;
  

  String getImage() 
    return image;
  

  String getDescription() 
    return description;
  

  String getPrice() 
    return price;
  

【讨论】:

【参考方案3】:

问题已解决,这是我的代码

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class MainPage extends StatefulWidget 
  const MainPage(Key key) : super(key: key);

  @override
  State<MainPage> createState() => _MainPageState();


class _MainPageState extends State<MainPage>
    with SingleTickerProviderStateMixin 
  Future<List<Product>> _getProducts() async 
    final dataString = await rootBundle.loadString('assets/product.json');
    final List<dynamic> json = jsonDecode(dataString);
    final products = <Product>[];
    for (var v in json) 
      products.add(Product.fromJson(v));
    
    return products;
  

  @override
  Widget build(BuildContext context) 
    return FutureBuilder<List<Product>>(
      future: _getProducts(),
      builder: (c, s) 
        if (s.hasData) 
          List<Tab> tabs = <Tab>[];

          for (int i = 0; i < s.data.length; i++) 
            tabs.add(Tab(
              child: Text(
                s.data[i].title,
              ),
            ));
          
          return DefaultTabController(
            length: s.data.length,
            child: Scaffold(
              appBar: AppBar(
                title: const Text("My Store"),
                bottom: TabBar(
                  isScrollable: true,
                  tabs: tabs,
                ),
              ),
              body: FutureBuilder<List<Product>>(
                future: _getProducts(),
                builder: (c, s) 
                  if (s.hasData) 
                    List<Widget> tabs = <Widget>[];

                    for (int i = 0; i < s.data.length; i++) 
                      tabs.add(Tab(
                        child: SingleChildScrollView(
                          physics: const BouncingScrollPhysics(
                              parent: AlwaysScrollableScrollPhysics()),
                          child: Padding(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 20, vertical: 0),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.start,
                              children: [
                                const SizedBox(height: 30),
                                Text(
                                  s.data[i].title,
                                  textAlign: TextAlign.center,
                                  style: const TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold),
                                ),
                                const SizedBox(height: 30),
                                Image.asset(s.data[i].image),
                                const SizedBox(height: 30),
                                Text(s.data[i].title),
                                const SizedBox(height: 30),
                                Text(s.data[i].description),
                              ],
                            ),
                          ),
                        ),
                      ));
                    
                    return TabBarView(
                      children: tabs,
                    );
                  
                  return Container();
                ,
              ),
            ),
          );
        
        return Scaffold(
          body: Center(
              child: Text(s.hasError ? s.error.toString() : "Loading...")),
        );
      ,
    );
  


// Product Model

List<Product> ProductFromJson(String str) =>
    List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));

class Product 
  Product(
    this.id,
    this.title,
    this.image,
    this.description,
    this.price,
  );

  final int id;
  final String title;
  final String image;
  final String description;
  final String price;

  factory Product.fromJson(Map<String, dynamic> json) => Product(
        id: json["id"],
        title: json["title"],
        image: json["image"],
        description: json["description"],
        price: json["price"],
      );

  String getTitle() 
    return title;
  

  String getImage() 
    return image;
  

  String getDescription() 
    return description;
  

  String getPrice() 
    return price;
  

【讨论】:

以上是关于Flutter:如何调用本地 JSON 数据并动态添加到标签栏?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter Mobile App 中加载和查询本地 json 数据

Flutter:如何从 JSON 创建收藏夹列表

如何在flutter中使用API​​调用嵌套的json数据?

如何使用 json 本地资产文件创建动态列表视图

如何在 Flutter 中调用 POST 函数

如何在flutter中读取本地json导入?