You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何保存JSON API请求数据?类电商应用如何实现商品收藏并在另一页展示?

实现Flutter电商应用的商品收藏功能与API数据存储

Hey there! Let's walk through how to build the favorite feature for your e-commerce app and handle saving JSON API data in Flutter. I'll break this down into actionable steps with code examples you can reuse directly.

第一步:把API返回的JSON转为Dart模型类

First, you'll want to convert the raw JSON from your API into strongly-typed Dart objects—this makes data handling safer and more maintainable. Suppose your product JSON looks like this:

{
  "id": 1,
  "name": "Wireless Headphones",
  "price": 99.99,
  "imageUrl": "https://example.com/headphones.jpg",
  "description": "Noise-cancelling over-ear headphones"
}

Use the json_serializable package to generate serialization code. First add dependencies to pubspec.yaml:

dependencies:
  json_annotation: ^4.8.1

dev_dependencies:
  build_runner: ^2.4.4
  json_serializable: ^6.7.0

Then create your product model:

import 'package:json_annotation/json_annotation.dart';

part 'product.g.dart';

@JsonSerializable()
class Product {
  final int id;
  final String name;
  final double price;
  final String imageUrl;
  final String description;

  Product({
    required this.id,
    required this.name,
    required this.price,
    required this.imageUrl,
    required this.description,
  });

  // Convert JSON to Product object
  factory Product.fromJson(Map<String, dynamic> json) => _$ProductFromJson(json);

  // Convert Product object to JSON
  Map<String, dynamic> toJson() => _$ProductToJson(this);
}

Run flutter pub run build_runner build to generate the serialization boilerplate—now you can easily convert between JSON and Dart objects.

第二步:选择合适的本地存储方案

Based on your needs (saving a list of favorite products), here are the most common and practical options:

方案1:SharedPreferences(适合小量数据)

If your favorite list won't grow too large (e.g., dozens of items), SharedPreferences is a simple choice—it stores basic types like strings. We'll serialize the product list into a JSON string for storage.

Create a storage service class:

import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import 'product.dart';

class FavoriteStorage {
  static const String _favoritesKey = 'favorite_products';

  // Add a product to favorites
  Future<void> addFavorite(Product product) async {
    final prefs = await SharedPreferences.getInstance();
    List<String> favorites = prefs.getStringList(_favoritesKey) ?? [];
    
    // Avoid duplicates
    bool isAlreadyFavorite = favorites.any((item) {
      return Product.fromJson(jsonDecode(item)).id == product.id;
    });
    
    if (!isAlreadyFavorite) {
      favorites.add(jsonEncode(product.toJson()));
      await prefs.setStringList(_favoritesKey, favorites);
    }
  }

  // Remove a product from favorites
  Future<void> removeFavorite(int productId) async {
    final prefs = await SharedPreferences.getInstance();
    List<String> favorites = prefs.getStringList(_favoritesKey) ?? [];
    
    favorites.removeWhere((item) {
      return Product.fromJson(jsonDecode(item)).id == productId;
    });
    
    await prefs.setStringList(_favoritesKey, favorites);
  }

  // Get all favorite products
  Future<List<Product>> getFavorites() async {
    final prefs = await SharedPreferences.getInstance();
    List<String> favorites = prefs.getStringList(_favoritesKey) ?? [];
    
    return favorites.map((item) => Product.fromJson(jsonDecode(item))).toList();
  }

  // Check if a product is already favorited
  Future<bool> isFavorite(int productId) async {
    final prefs = await SharedPreferences.getInstance();
    List<String> favorites = prefs.getStringList(_favoritesKey) ?? [];
    
    return favorites.any((item) {
      return Product.fromJson(jsonDecode(item)).id == productId;
    });
  }
}

方案2:Hive(适合结构化数据,操作更便捷)

Hive is a lightweight NoSQL database that lets you store Dart objects directly (no manual JSON serialization needed). It's faster than SharedPreferences and great for medium-sized datasets.

Add dependencies first:

dependencies:
  hive: ^2.2.3
  hive_flutter: ^1.1.0

dev_dependencies:
  hive_generator: ^1.1.5
  build_runner: ^2.4.4

Initialize Hive in your main() function and register the adapter:

void main() async {
  await Hive.initFlutter();
  Hive.registerAdapter(ProductAdapter()); // Generated adapter
  runApp(MyApp());
}

Update your Product model to work with Hive:

import 'package:hive/hive.dart';

part 'product.g.dart';

@HiveType(typeId: 0) // Unique ID for this object type
class Product extends HiveObject {
  @HiveField(0)
  final int id;
  @HiveField(1)
  final String name;
  @HiveField(2)
  final double price;
  @HiveField(3)
  final String imageUrl;
  @HiveField(4)
  final String description;

  Product({
    required this.id,
    required this.name,
    required this.price,
    required this.imageUrl,
    required this.description,
  });
}

Run flutter pub run build_runner build to generate the adapter, then create the Hive storage service:

import 'package:hive/hive.dart';
import 'product.dart';

class FavoriteStorage {
  late Box<Product> _favoriteBox;

  Future<void> init() async {
    _favoriteBox = await Hive.openBox<Product>('favorite_products');
  }

  Future<void> addFavorite(Product product) async {
    if (!_favoriteBox.containsKey(product.id)) {
      await _favoriteBox.put(product.id, product);
    }
  }

  Future<void> removeFavorite(int productId) async {
    await _favoriteBox.delete(productId);
  }

  List<Product> getFavorites() {
    return _favoriteBox.values.toList();
  }

  bool isFavorite(int productId) {
    return _favoriteBox.containsKey(productId);
  }
}

Don't forget to call await FavoriteStorage().init() when your app starts.

方案3:SQFlite(适合复杂查询场景)

If you need advanced filtering, sorting, or have a large dataset, SQFlite (Flutter's SQLite wrapper) is the way to go. It's more verbose but offers full SQL capabilities.

Add dependencies:

dependencies:
  sqflite: ^2.3.0
  path: ^1.8.3

Create a database helper class:

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'product.dart';

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  factory DatabaseHelper() => _instance;
  DatabaseHelper._internal();

  static Database? _database;

  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  Future<Database> _initDatabase() async {
    String path = join(await getDatabasesPath(), 'ecommerce.db');
    return await openDatabase(
      path,
      version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE products(
            id INTEGER PRIMARY KEY,
            name TEXT,
            price REAL,
            imageUrl TEXT,
            description TEXT
          )
        ''');
      },
    );
  }

  Future<void> addFavorite(Product product) async {
    final db = await database;
    await db.insert(
      'products',
      product.toJson(),
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  Future<void> removeFavorite(int productId) async {
    final db = await database;
    await db.delete(
      'products',
      where: 'id = ?',
      whereArgs: [productId],
    );
  }

  Future<List<Product>> getFavorites() async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query('products');
    return List.generate(maps.length, (i) {
      return Product.fromJson(maps[i]);
    });
  }

  Future<bool> isFavorite(int productId) async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query(
      'products',
      where: 'id = ?',
      whereArgs: [productId],
    );
    return maps.isNotEmpty;
  }
}

第三步:实现收藏图标点击逻辑

Add a favorite icon to your product list item or detail page, with toggle functionality:

import 'package:flutter/material.dart';
import 'product.dart';
import 'favorite_storage.dart';

class ProductItem extends StatefulWidget {
  final Product product;

  const ProductItem({super.key, required this.product});

  @override
  State<ProductItem> createState() => _ProductItemState();
}

class _ProductItemState extends State<ProductItem> {
  late FavoriteStorage _storage;
  bool _isFavorite = false;

  @override
  void initState() {
    super.initState();
    _storage = FavoriteStorage();
    _checkFavoriteStatus();
  }

  Future<void> _checkFavoriteStatus() async {
    bool status = await _storage.isFavorite(widget.product.id);
    setState(() {
      _isFavorite = status;
    });
  }

  Future<void> _toggleFavorite() async {
    if (_isFavorite) {
      await _storage.removeFavorite(widget.product.id);
    } else {
      await _storage.addFavorite(widget.product);
    }
    setState(() {
      _isFavorite = !_isFavorite;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        children: [
          Image.network(widget.product.imageUrl, height: 150, fit: BoxFit.cover),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(widget.product.name, style: const TextStyle(fontSize: 16)),
          ),
          Text('\$${widget.product.price.toStringAsFixed(2)}'),
          IconButton(
            icon: Icon(
              _isFavorite ? Icons.favorite : Icons.favorite_border,
              color: _isFavorite ? Colors.red : null,
            ),
            onPressed: _toggleFavorite,
          ),
        ],
      ),
    );
  }
}

第四步:展示收藏列表页面

Create a page to load and display all favorite products:

import 'package:flutter/material.dart';
import 'favorite_storage.dart';
import 'product.dart';
import 'product_item.dart';

class FavoritesPage extends StatefulWidget {
  const FavoritesPage({super.key});

  @override
  State<FavoritesPage> createState() => _FavoritesPageState();
}

class _FavoritesPageState extends State<FavoritesPage> {
  late FavoriteStorage _storage;
  List<Product> _favoriteProducts = [];

  @override
  void initState() {
    super.initState();
    _storage = FavoriteStorage();
    _loadFavorites();
  }

  Future<void> _loadFavorites() async {
    List<Product> products = await _storage.getFavorites();
    setState(() {
      _favoriteProducts = products;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('My Favorites')),
      body: _favoriteProducts.isEmpty
          ? const Center(child: Text('No favorite products yet'))
          : GridView.builder(
              padding: const EdgeInsets.all(8),
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                crossAxisSpacing: 8,
                mainAxisSpacing: 8,
                childAspectRatio: 0.75,
              ),
              itemCount: _favoriteProducts.length,
              itemBuilder: (context, index) {
                return ProductItem(product: _favoriteProducts[index]);
              },
            ),
    );
  }
}

快速方案选择指南

  • SharedPreferences: Best for small datasets (dozens of items), simplest implementation.
  • Hive: Best for structured objects, easy to use, better performance than SharedPreferences.
  • SQFlite: Best for large datasets or when you need advanced SQL queries.

No matter which option you pick, the core flow is the same: serialize and save product data when the user taps favorite, then deserialize and display it in the favorites page.

内容的提问来源于stack exchange,提问作者EDMGL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 15:57:42