MST

星途 面试题库

面试题:Flutter网络请求缓存策略之高级难度题

假设你正在开发一个Flutter应用,需要缓存图片的网络请求。要求实现一个缓存策略,能够根据图片的URL进行缓存,并且当缓存过期时,优先从缓存中获取图片并显示,同时在后台更新缓存。请详细描述实现思路以及关键代码片段。
32.8万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 选择缓存库:在Flutter中,可以使用cached_network_image库来实现图片缓存。它已经内置了根据URL缓存图片的功能。
  2. 设置缓存过期策略:可以通过自定义缓存管理类来实现过期策略。例如,记录图片缓存的时间戳,每次获取图片时检查时间戳与当前时间的差值,判断是否过期。
  3. 优先从缓存获取并后台更新:当图片过期时,先从缓存中获取旧图片显示,然后在后台发起新的网络请求更新缓存。

关键代码片段

  1. 引入依赖: 在pubspec.yaml文件中添加cached_network_image依赖:
dependencies:
  cached_network_image: ^3.2.3
  1. 自定义缓存管理类(示例)
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';

class CustomCacheManager extends BaseCacheManager {
  static const key = 'customCacheKey';
  final _prefs = SharedPreferences.getInstance();
  static CustomCacheManager _instance;

  factory CustomCacheManager() => _instance??= CustomCacheManager._();
  CustomCacheManager._() : super(key);

  @override
  Future<File> getFile(String url) async {
    final file = await super.getFile(url);
    if (file.existsSync()) {
      final prefs = await _prefs;
      final timestamp = prefs.getDouble('$url - timestamp');
      final now = DateTime.now().millisecondsSinceEpoch / 1000;
      if (timestamp != null && now - timestamp > 3600) { // 假设缓存1小时过期
        // 后台更新缓存
        _updateCacheInBackground(url);
      }
      return file;
    }
    return super.getFile(url);
  }

  Future<void> _updateCacheInBackground(String url) async {
    final file = await super.getFile(url);
    if (file.existsSync()) {
      final prefs = await _prefs;
      await prefs.setDouble('$url - timestamp', DateTime.now().millisecondsSinceEpoch / 1000);
    }
  }
}
  1. 使用自定义缓存管理器显示图片
class MyHomePage extends StatelessWidget {
  final String imageUrl = 'https://example.com/image.jpg';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Cached Image'),
      ),
      body: Center(
        child: CachedNetworkImage(
          imageUrl: imageUrl,
          cacheManager: CustomCacheManager(),
          placeholder: (context, url) => CircularProgressIndicator(),
          errorWidget: (context, url, error) => Icon(Icons.error),
        ),
      ),
    );
  }
}