Flutter网络请求与缓存插件dio_http_cache_cjfork的使用

Flutter网络请求与缓存插件dio_http_cache_cjfork的使用

dio-http-cache

Pub

中文介绍

Dio-http-cache 是一个用于 [Dio (Flutter 的 HTTP 客户端)] 的缓存库,类似于 Android 中的 Rxcache。

Dio-http-cache 使用 sqflite 作为磁盘缓存,并使用 LRU 策略作为内存缓存。

灵感来源于 flutter_cache_manager。

添加依赖

dependencies:
  dio_http_cache_cjfork: ^0.3.x #最新版本

快速开始

  1. 在 Dio 中添加 dio-http-cache 拦截器:
dio.interceptors.add(DioCacheManager(CacheConfig(baseUrl: "http://www.google.com")).interceptor);
  1. 设置请求的最大缓存时间:
Dio().get(
  "http://www.google.com",
  options: buildCacheOptions(Duration(days: 7)),
);

高级用法

  1. 通过 buildCacheOptions 自定义配置:

    • primaryKey: 默认情况下,host + path 用作 primaryKey,你也可以自定义它。
    • subKey: 默认情况下,query (data 或 queryParameters) 用作 subKey,必要时可以指定 subKey,例如:
    buildCacheOptions(Duration(days: 7), subKey: "page=1")
    
    • maxAge: 设置缓存时间。如果值为 null 或未设置,则会尝试从响应头中获取 maxAge 和 maxStale。
    buildCacheOptions(Duration(days: 7), maxStale: Duration(days: 10))
    
    • forceRefresh: 默认为 false。
    buildCacheOptions(Duration(days: 7), forceRefresh: true)
    
    1. 先从网络获取数据。
    2. 如果从网络获取数据成功,则存储或刷新缓存。
    3. 如果从网络获取数据失败或没有网络可用,则尝试从缓存中获取数据而不是报错。
  2. 使用 “CacheConfig” 来配置默认参数

    • baseUrl: 可选;如果你在 CacheConfig 中没有设置 baseUrl,在调用 deleteCache 时需要提供完整的路径,如 "https://www.google.com/search?q=hello",而不是 "search?q=hello"

    • encrypt / decrypt: 这两个必须一起使用来加密磁盘缓存数据,你也可以在这里压缩数据。

    • defaultMaxAge: 默认使用 Duration(day:7)

    • defaultaMaxStale: 类似于 DefaultMaxAge。

    • databasePath: 数据库路径。

    • databaseName: 数据库名称。

    • skipMemoryCache: 默认为 false。

    • skipDiskCache: 默认为 false。

    • maxMemoryCacheCount: 默认为 100。

    • defaultRequestMethod: 默认使用 “POST”,这将用于 delete caches

    • diskStore: 自定义磁盘存储。

  3. 如何清除过期缓存

    • 直接忽略即可,这是自动的。

    • 但是如果你坚持这样做:DioCacheManager.clearExpired();

  4. 如何删除缓存

    • 无论 subKey 是什么,只要 primaryKey 匹配就删除本地缓存:
    // 自动解析 primaryKey 从路径
    _dioCacheManager.deleteByPrimaryKey(path, requestMethod: "POST"); 
    
    • 当 primaryKey 和 subKey 都匹配时删除本地缓存。
    // 当 primaryKey 和 subKey 都匹配时删除本地缓存。
    _dioCacheManager.deleteByPrimaryKeyAndSubKey(path, requestMethod: "GET"); 
    

    重要提示: 如果你在请求 HTTP 接口时有额外的参数,你必须带上它们,例如:

    _dio.get(_url, queryParameters: {'k': keyword}, 
        options: buildCacheOptions(Duration(hours: 1)))
    // 删除缓存:
    _dioCacheManager.deleteByPrimaryKeyAndSubKey(_url, requestMethod: "GET", queryParameters:{'k': keyword}); 
    
    _dio.post(_url, data: {'k': keyword}, 
        options: buildCacheOptions(Duration(hours: 1)))
    // 删除缓存:
    _dioCacheManager.deleteByPrimaryKeyAndSubKey(_url, requestMethod: "POST", data:{'k': keyword}); 
    
    • 通过 primaryKey 和可选的 subKey 删除本地缓存,如果你确切知道你的 primaryKey 和 subkey。
    // 通过 primaryKey 和可选的 subKey 删除本地缓存
    _dioCacheManager.delete(primaryKey,{subKey,requestMethod});
    
  5. 如何清除所有缓存(过期或未过期)

    _dioCacheManager.clearAll();
    
  6. 如何知道数据是否来自缓存

    if (null != response.headers.value(DIO_CACHE_HEADER_KEY_DATA_SOURCE)) {
        // 数据来自缓存
    } else {
        // 数据来自网络
    }
    

maxAge 和 maxStale 示例

_dio.post(
    "https://www.exmaple.com",
    data: {'k': "keyword"},
    options:buildCacheOptions(
        Duration(days: 3), 
        maxStale: Duration(days: 7), 
    )
)
  • 0 ~ 3 天:直接从缓存返回数据(与网络无关)。

  • 3 ~ 7 天:

    1. 首先从网络获取数据。
    2. 如果从网络获取数据成功,则刷新缓存。
    3. 如果从网络获取数据失败或没有网络可用,则尝试从缓存中获取数据而不是报错。
  • 7 ~ ∞ 天:不再使用缓存,并且缓存在适当的时间内会被删除。

许可证

Copyright 2019 Hurshi

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

示例代码

example/lib/main.dart

import 'package:flutter/material.dart';

import 'panels/cache_manage.dart';
import 'panels/panel_204.dart';
import 'panels/panel_get.dart';
import 'panels/panel_get_bytes.dart';
import 'panels/panel_get_from_service.dart';
import 'panels/panel_post.dart';
import 'tuple.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    final title = "DioHttpCache Example";
    return MaterialApp(
        title: title,
        theme: ThemeData(primarySwatch: Colors.blue),
        home: MyHomePage(title: title));
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);
  final String? title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

enum Panel { CACHE_MANAGER, POST, POST_204, GET_FROM_SERVICE, GET, GET_BYTES }

class _MyHomePageState extends State<MyHomePage> {
  Panel panel = Panel.POST;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text(widget.title!),
            actions: <Widget>[_buildHomePageActionButtons(context)]),
        body: getPanel());
  }

  Widget? getPanel() {
    switch (panel) {
      case Panel.CACHE_MANAGER:
        return CacheManagerPanel();
      case Panel.GET:
        return GetPanel();
      case Panel.POST:
        return PostPanel();
      case Panel.POST_204:
        return Post204Panel();
      case Panel.GET_FROM_SERVICE:
        return PostGetLetServicePanel();
      case Panel.GET_BYTES:
        return GetBytesPanel();
    }
  }

  Widget _buildHomePageActionButtons(BuildContext context) {
    List<Pair<String, Function()>> choices = [
      Pair("Cache Manager", () => setState(() => panel = Panel.CACHE_MANAGER)),
      Pair("POST", () => setState(() => panel = Panel.POST)),
      Pair("POST 204", () => setState(() => panel = Panel.POST_204)),
      Pair("GET", () => setState(() => panel = Panel.GET)),
      Pair("GET from service", () => setState(() => panel = Panel.GET_FROM_SERVICE)),
      Pair("GET byte array", () => setState(() => panel = Panel.GET_BYTES)),
    ];
    return PopupMenuButton<Pair<String, Function()>>
    (
        onSelected: (p) => p.i1!(),
        child: Padding(
            padding: EdgeInsets.all(10),
            child: Icon(Icons.menu, color: Colors.white)),
        itemBuilder: (BuildContext context) => choices
            .map((choice) => PopupMenuItem<Pair<String, Function()>>
            (
                value: choice, child: Text(choice.i0!)))
            .toList());
  }
}

更多关于Flutter网络请求与缓存插件dio_http_cache_cjfork的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络请求与缓存插件dio_http_cache_cjfork的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


dio_http_cache_cjfork 是一个基于 dio 的网络请求缓存插件,它可以帮助你在 Flutter 应用中轻松实现网络请求的缓存功能。以下是如何使用 dio_http_cache_cjfork 的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 dio_http_cache_cjfork 依赖:

dependencies:
  flutter:
    sdk: flutter
  dio: ^4.0.0
  dio_http_cache_cjfork: ^0.3.0

然后运行 flutter pub get 来安装依赖。

2. 初始化 Dio 并配置缓存

在你的 Dart 文件中,导入 diodio_http_cache_cjfork,然后初始化 Dio 并配置缓存。

import 'package:dio/dio.dart';
import 'package:dio_http_cache_cjfork/dio_http_cache_cjfork.dart';

void main() {
  // 初始化 Dio
  Dio dio = Dio();

  // 配置缓存
  dio.interceptors.add(
    DioCacheManager(
      CacheConfig(
        baseUrl: "https://example.com", // 你的 API 基础 URL
        defaultMaxAge: Duration(days: 7), // 默认缓存有效期
        maxMemoryCacheCount: 100, // 最大内存缓存数量
        skipMemoryCache: false, // 是否跳过内存缓存
        skipDiskCache: false, // 是否跳过磁盘缓存
      ),
    ).interceptor,
  );

  // 使用 Dio 发起请求
  fetchData(dio);
}

void fetchData(Dio dio) async {
  try {
    var response = await dio.get(
      '/api/data',
      options: buildCacheOptions(Duration(days: 1)), // 设置缓存有效期
    );
    print(response.data);
  } catch (e) {
    print(e);
  }
}

3. 使用 buildCacheOptions 配置请求缓存

在发起请求时,你可以使用 buildCacheOptions 方法来配置每个请求的缓存行为。例如:

var response = await dio.get(
  '/api/data',
  options: buildCacheOptions(Duration(days: 1)), // 设置缓存有效期
);

buildCacheOptions 方法可以接受以下参数:

  • maxAge: 缓存的最大有效期。
  • forceRefresh: 是否强制刷新缓存。
  • subKey: 缓存的子键,用于区分同一 URL 的不同请求。
  • skipMemoryCache: 是否跳过内存缓存。
  • skipDiskCache: 是否跳过磁盘缓存。

4. 清除缓存

你可以使用 DioCacheManager 来清除缓存:

DioCacheManager().clearAll(); // 清除所有缓存
DioCacheManager().delete('/api/data'); // 清除指定 URL 的缓存

5. 其他配置

你还可以通过 CacheConfig 类来配置全局缓存行为,例如:

CacheConfig(
  baseUrl: "https://example.com", // 你的 API 基础 URL
  defaultMaxAge: Duration(days: 7), // 默认缓存有效期
  maxMemoryCacheCount: 100, // 最大内存缓存数量
  skipMemoryCache: false, // 是否跳过内存缓存
  skipDiskCache: false, // 是否跳过磁盘缓存
)
回到顶部