Flutter中如何仅调用一次Rest API并复用内存数据
优化方案:单次API调用+内存缓存读取产品数据
1. 创建全局内存缓存单例
用单例类存储产品数据,确保整个APP内只有一份缓存实例,避免重复请求:
class ProductCache { static final ProductCache _instance = ProductCache._internal(); List<PostListOfProducts>? _cachedProducts; factory ProductCache() => _instance; ProductCache._internal(); // 存入缓存数据 void setProducts(List<PostListOfProducts> products) { _cachedProducts = products; } // 获取缓存数据 List<PostListOfProducts>? getProducts() { return _cachedProducts; } // 登出时清空缓存,避免用户数据混淆 void clearCache() { _cachedProducts = null; } }
2. 修改API请求逻辑,优先读取缓存
修改getPosts方法,先检查缓存,无缓存时再发起API请求,成功后存入缓存:
static Future<List<PostListOfProducts>> getPosts() async { // 先读缓存,有数据直接返回 final cachedProducts = ProductCache().getProducts(); if (cachedProducts != null) { return cachedProducts; } SharedPreferences prefs = await SharedPreferences.getInstance(); final token = await prefs.getString('token'); final loginEmail = await prefs.getString('dietetyk'); Response response = await post(Uri.parse('https://some_page.com'), headers: <String, String>{ 'Accept': 'application/json', 'Authorization': 'Bearer $token', }, body: <String, String>{ 'loginEmail': loginEmail, }, ); if(response.statusCode != 200){ print('Błąd połączenia z bazą danych... status[${response.statusCode}]'); throw Exception('Nie udało się załadować produktów'); } final List body = json.decode(response.body); final products = body.map((e) => PostListOfProducts.fromJson(e)).toList(); // 请求成功后存入缓存 ProductCache().setProducts(products); return products; }
同时修改PostListOfProductsAPI的搜索逻辑,直接从缓存过滤数据,不再重复发起API请求:
class PostListOfProductsAPI { static Future<List<PostListOfProducts>> getUserSuggestions(String query) async { // 先读缓存,缓存为空则先调用getPosts获取数据 final cachedProducts = ProductCache().getProducts() ?? await getPosts(); return _filterProducts(cachedProducts, query); } // 抽离搜索过滤逻辑 static List<PostListOfProducts> _filterProducts(List<PostListOfProducts> products, String query) { final queryLower = query.toLowerCase(); return products.where((product) => product.nazwa!.toLowerCase().contains(queryLower) ).toList(); } }
3. 优化页面FutureBuilder的使用
避免将postsFuture定义为顶级变量(页面重建时会重复触发请求),改为在initState中初始化:
late Future<List<PostListOfProducts>> postsFuture; @override void initState() { super.initState(); postsFuture = getPosts(); } // 原build方法保持不变 Widget build(BuildContext context) { return Scaffold( // ... 原有代码 body: FutureBuilder<List<PostListOfProducts>>( future: postsFuture, builder: (context, snapshot) { // ... 原有builder逻辑 }, ), ); }
4. 登出时清空缓存
在signUserOut方法中加入清空缓存的逻辑,防止切换用户后数据残留:
void signUserOut() async { // 原有登出逻辑 await FirebaseAuth.instance.signOut(); // 清空产品缓存 ProductCache().clearCache(); // 跳转到登录页等后续操作 }
内容的提问来源于stack exchange,提问作者bzc0fq
相关产品推荐
相关产品推荐

