MST

星途 面试题库

面试题:Flutter异步加载缓存策略下如何处理缓存数据的过期与更新

在Flutter使用异步加载缓存策略时,缓存的数据可能会过期需要更新。阐述你会如何设计缓存数据过期机制以及数据更新流程,同时说明在多请求并发情况下如何保证缓存数据的一致性和准确性,给出相应设计思路和关键代码片段。
41.1万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

缓存数据过期机制设计思路

  1. 记录缓存时间戳:在缓存数据时,同时记录数据的缓存时间戳。当获取缓存数据时,通过当前时间与缓存时间戳比较,判断数据是否过期。
  2. 设置过期时间:为每种缓存数据设置一个合理的过期时间(TTL,Time To Live)。例如,一些实时性要求不高的数据可以设置较长的过期时间,而实时性要求高的数据设置较短过期时间。

数据更新流程设计思路

  1. 检查过期:在获取缓存数据前,先检查数据是否过期。如果过期,启动更新流程。
  2. 异步更新:使用异步任务去更新缓存数据。在更新过程中,可以先返回旧的缓存数据(如果允许的话),以保证用户体验。
  3. 更新成功后替换:当异步更新任务成功获取到新数据后,替换旧的缓存数据。

多请求并发情况下保证缓存数据一致性和准确性

  1. 锁机制:使用锁(如Lock)来保证在同一时间只有一个请求可以更新缓存数据。其他请求在等待锁释放后,检查缓存是否已更新,如果已更新则直接使用,否则再进行更新。
  2. 版本控制:为缓存数据添加版本号。每次更新数据时,版本号递增。请求获取数据时,检查版本号,若发现版本号不一致,重新获取数据。

关键代码片段

  1. 缓存数据存储与过期检查
import 'package:flutter/material.dart';
import 'dart:async';

class CacheManager {
  Map<String, dynamic> _cache = {};
  Map<String, DateTime> _cacheTimestamps = {};
  Duration _ttl = const Duration(minutes: 5);

  Future<dynamic> getCache(String key) async {
    if (_cache.containsKey(key) &&
        DateTime.now().difference(_cacheTimestamps[key]!) < _ttl) {
      return _cache[key];
    } else {
      // 数据过期,返回null或启动更新流程
      return null;
    }
  }

  void setCache(String key, dynamic value) {
    _cache[key] = value;
    _cacheTimestamps[key] = DateTime.now();
  }
}
  1. 异步更新缓存数据
Future<dynamic> updateCache(CacheManager cacheManager, String key) async {
  // 模拟异步获取新数据
  await Future.delayed(const Duration(seconds: 2));
  dynamic newData = "new data"; 
  cacheManager.setCache(key, newData);
  return newData;
}
  1. 使用锁机制保证一致性(简化示例)
import 'dart:async';
import 'dart:io';

void main() async {
  CacheManager cacheManager = CacheManager();
  Lock lock = Lock();

  Future<void> fetchData(String key) async {
    await lock.synchronized(() async {
      dynamic data = await cacheManager.getCache(key);
      if (data == null) {
        data = await updateCache(cacheManager, key);
      }
      print('Fetched data: $data');
    });
  }

  // 模拟多个并发请求
  List<Future<void>> requests = [];
  for (int i = 0; i < 5; i++) {
    requests.add(fetchData('testKey'));
  }
  await Future.wait(requests);
}
  1. 版本控制(简单示例)
class VersionedCacheManager {
  Map<String, dynamic> _cache = {};
  Map<String, int> _cacheVersions = {};

  Future<dynamic> getCache(String key, int expectedVersion) async {
    if (_cache.containsKey(key) &&
        _cacheVersions[key] == expectedVersion) {
      return _cache[key];
    } else {
      return null;
    }
  }

  void setCache(String key, dynamic value) {
    _cache[key] = value;
    _cacheVersions[key] = (_cacheVersions[key]?? 0) + 1;
  }
}