在 Flutter 中,我如何使用 API 和 GetX 在 JSON 中获取数据

Posted

技术标签:

【中文标题】在 Flutter 中,我如何使用 API 和 GetX 在 JSON 中获取数据【英文标题】:In Flutter how I can fetch data inside a JASON with API and GetX 【发布时间】:2021-06-17 04:11:19 【问题描述】:

在 Flutter 中,我尝试过这种方式,但没有任何输出。我想从保存 JASON 数据的 URL 中获取数据,并根据名称、价格、图像等获取所有数据。但我无法使用以下方法。代码有什么问题。谁能帮我?谢谢。

这是我的 product_model.dart 文件

// To parse this JSON data, do
//
//     final product = productFromJson(jsonString);

import 'dart:convert';

Product productFromJson(String str) => Product.fromJson(json.decode(str));

String productToJson(Product data) => json.encode(data.toJson());

class Product 
    Product(
        this.code,
        this.meta,
        this.data,
    );

    int code;
    Meta meta;
    List<Datum> data;

    factory Product.fromJson(Map<String, dynamic> json) => Product(
        code: json["code"],
        meta: Meta.fromJson(json["meta"]),
        data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
    );

    Map<String, dynamic> toJson() => 
        "code": code,
        "meta": meta.toJson(),
        "data": List<dynamic>.from(data.map((x) => x.toJson())),
    ;


class Datum 
    Datum(
        this.id,
        this.name,
        this.description,
        this.image,
        this.price,
        this.discountAmount,
        this.status,
        this.categories,
    );

    int id;
    String name;
    String description;
    String image;
    String price;
    String discountAmount;
    bool status;
    List<Category> categories;

    factory Datum.fromJson(Map<String, dynamic> json) => Datum(
        id: json["id"],
        name: json["name"],
        description: json["description"],
        image: json["image"],
        price: json["price"],
        discountAmount: json["discount_amount"],
        status: json["status"],
        categories: List<Category>.from(json["categories"].map((x) => Category.fromJson(x))),
    );

    Map<String, dynamic> toJson() => 
        "id": id,
        "name": name,
        "description": description,
        "image": image,
        "price": price,
        "discount_amount": discountAmount,
        "status": status,
        "categories": List<dynamic>.from(categories.map((x) => x.toJson())),
    ;


class Category 
    Category(
        this.id,
        this.name,
    );

    int id;
    String name;

    factory Category.fromJson(Map<String, dynamic> json) => Category(
        id: json["id"],
        name: json["name"],
    );

    Map<String, dynamic> toJson() => 
        "id": id,
        "name": name,
    ;


class Meta 
    Meta(
        this.pagination,
    );

    Pagination pagination;

    factory Meta.fromJson(Map<String, dynamic> json) => Meta(
        pagination: Pagination.fromJson(json["pagination"]),
    );

    Map<String, dynamic> toJson() => 
        "pagination": pagination.toJson(),
    ;


class Pagination 
    Pagination(
        this.total,
        this.pages,
        this.page,
        this.limit,
    );

    int total;
    int pages;
    int page;
    int limit;

    factory Pagination.fromJson(Map<String, dynamic> json) => Pagination(
        total: json["total"],
        pages: json["pages"],
        page: json["page"],
        limit: json["limit"],
    );

    Map<String, dynamic> toJson() => 
        "total": total,
        "pages": pages,
        "page": page,
        "limit": limit,
    ;

这是我的 api_service.dart 文件

import 'package:http/http.dart' as http;
import 'package:mashmart/models/product_model.dart';

class ApiService 
  static var client = http.Client();

  static Future<List<Product>> fetchProducts() async 
    var url = Uri.https(
        'https://gorest.co.in', '/public-api/products');
    var response = await client.get(url);

    if (response.statusCode == 200) 
      var jasonString = response.body;
      return productFromJson(jasonString);
     else 
      print('Request failed with status: $response.statusCode.');
      return null;
    
  

这是我的 product_controller.dart 文件

import 'package:get/state_manager.dart';
import 'package:mashmart/models/product_model.dart';
import 'package:mashmart/services/api_service.dart';

class ProductController extends GetxController 
  var isLoading = true.obs;
  var productList = List<Product>().obs;

  @override
  void onInit() 
    fetchProducts();
    super.onInit();
  

  void fetchProducts() async 
    try
      isLoading(true);
      var products = await ApiService.fetchProducts();
      if(products != null)
        productList.value = products;
      
     finally 
      isLoading(false);
    
  

这是我的 homepage.dart 文件

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:get/get.dart';
import 'package:mashmart/controllers/product_controller.dart';
import 'package:mashmart/services/api_service.dart';
import 'package:mashmart/views/products/product_tile.dart';

class HomePage extends StatelessWidget 
  final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();

  final ProductController productController = Get.put(ProductController());

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      key: _key,
      drawer: Drawer(),
      appBar: AppBar(
        title: Text(
          "Category",
          style: TextStyle(color: Colors.black87),
        ),
        centerTitle: true,
        elevation: 0.0,
        backgroundColor: Colors.grey[100],
        leading: IconButton(
          icon: Icon(Icons.menu_rounded),
          color: Colors.black87,
          onPressed: () 
            print("Drawer Menu Clicked");
            _key.currentState.openDrawer();
          ,
        ),
        actions: <Widget>[
          Stack(
            children: [
              IconButton(
                  icon: Icon(
                    Icons.shopping_cart,
                    size: 30,
                    color: Colors.black87,
                  ),
                  onPressed: () 
                    print("Cart Clicked");
                  ),
              Positioned(
                top: 20,
                right: 4,
                child: Container(
                  height: 22,
                  width: 22,
                  padding: EdgeInsets.all(4),
                  decoration: BoxDecoration(
                      shape: BoxShape.circle, color: Colors.deepPurple),
                  child: Center(
                    child: Text(
                      "0",
                      style: TextStyle(
                          fontSize: 12,
                          fontWeight: FontWeight.bold,
                          color: Colors.white),
                    ),
                  ),
                ),
              ),
            ],
          ),
          Stack(
            children: [
              IconButton(
                  icon: Icon(
                    Icons.notifications_rounded,
                    size: 30,
                    color: Colors.black87,
                  ),
                  onPressed: () 
                    print("Notifications Clicked");
                  ),
              Positioned(
                top: 20,
                right: 4,
                child: Container(
                  height: 22,
                  width: 22,
                  padding: EdgeInsets.all(4),
                  decoration: BoxDecoration(
                      shape: BoxShape.circle, color: Colors.deepPurple),
                  child: Center(
                    child: Text(
                      "0",
                      style: TextStyle(
                          fontSize: 12,
                          fontWeight: FontWeight.bold,
                          color: Colors.white),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                Expanded(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      TextFormField(
                        decoration: InputDecoration(
                            hintText: "Search for markets or products",
                            prefixIcon: Icon(Icons.search_rounded),
                            border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(10),
                            )),
                        onTap: () 
                          print("Search Box Tapped");
                        ,
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                Expanded(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: <Widget>[
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: <Widget>[
                          Text(
                            "Products",
                            style: TextStyle(
                                fontSize: 18,
                                fontWeight: FontWeight.bold,
                                color: Colors.black87),
                          ),
                          Row(
                            children: [
                              IconButton(
                                  icon: Icon(
                                    Icons.list_rounded,
                                    color: Colors.black87,
                                  ),
                                  onPressed: () 
                                    print("List Clicked");
                                  ),
                              IconButton(
                                  icon: Icon(
                                    Icons.grid_view,
                                    color: Colors.black,
                                  ),
                                  onPressed: () 
                                    print("Grid Clicked");
                                  ),
                            ],
                          )
                        ],
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
          Expanded(
            child: Obx(() 
              if (productController.isLoading.value)
                return Center(child: CircularProgressIndicator());
              else
                print("Total Products = " +
                    productController.productList.length.toString());
              return ListView.builder(
                itemCount: productController.productList.length,
                itemBuilder: (context, index) 
                  return Column(
                    children: [
                      Row(
                        children: [
                          Container(
                            width: 150,
                            height: 100,
                            margin: EdgeInsets.fromLTRB(16, 8, 8, 8),
                            child: ClipRRect(
                              borderRadius: BorderRadius.circular(8),
                              child: Image.network(
                                productController.productList[index].image,
                                width: 150,
                                height: 100,
                                fit: BoxFit.fill,
                                color: Colors.red,
                                colorBlendMode: BlendMode.color,
                              ),
                            ),
                          ),
                          Flexible(
                              child: Column(
                            mainAxisAlignment: MainAxisAlignment.start,
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                productController.,
                                style: TextStyle(fontSize: 18),
                              ),
                              Text(
                                productController.productList[index].name,
                                style: TextStyle(fontSize: 18),
                              ),
                            ],
                          ))
                        ],
                      ),
                      Container(
                        color: Colors.black12,
                        height: 2,
                      )
                    ],
                  );
                ,
              );
            ),
          )
        ],
      ),
    );
  

【问题讨论】:

【参考方案1】:

首先,您可以验证该网站上的模型是否正确创建: https://app.quicktype.io/

如果一切正常,问题可能出在这一行:

return Product.productFromJson (jasonString);

在它返回的数据类型中,如果你注意到它不是一个数组,它是一个单一的对象,在这种情况下,函数应该是:

Future <Product> fetchProducts () async ...

【讨论】:

谢谢。如何获取产品详细信息并获取它们?【参考方案2】:
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      drawer: Drawer(),
      appBar: buildAppBar(),
      body: Column(
        children: [
          buildTextInputSearch(),
          buildProductsToolBar(),
          Obx(() => buildResultList()),
        ],
      ),
    );
  
  /* ---------------------------------------------------------------------------- */
  Widget buildResultList() 
    GoRestService goRest = Get.find();

    return Expanded(
      child: goRest.isLoading.value!
        ? Center(child: CircularProgressIndicator())
        : ListView.builder(
          itemCount: goRest.numOfProducts,
          itemBuilder: (context, index) => Column(
            children: [

结果:

完整代码可以在here找到。

【讨论】:

以上是关于在 Flutter 中,我如何使用 API 和 GetX 在 JSON 中获取数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中使用 Razorpay 订单 API?

如何在 Flutter 中使用 Google API?

如何在 Flutter 中使用 Provider 正确获取 API

如何使用 Dio 在 Flutter 中调用 API?

如何使用免费和公共的 Rapid API 并在 Flutter 应用程序中调用 API

如何在 Flutter 中使用 CoinMarketCap API