background

The cached_network_image control is usually used to display images in Flutter. This control requests images using the HTTP library. The HTTP library cannot add interceptors as easily as dio can.

implementation

CachedNetworkImage uses Flutter_cache_manager for image caching. You can use custom cache_manager to replace HTTP with DIO. As follows:

Custom CacheManager

class DioCacheManager extends CacheManager {
  static const key = 'dioCache';

  static DioCacheManager _instance;

  factory DioCacheManager(Dio dio) {
    if (_instance == null) {
      _instance = DioCacheManager._(dio);
    }
    return _instance;
  }

  DioCacheManager._(Dio dio)
      : super(Config(key, fileService: DioHttpFileService(dio)));
}
Copy the code

Custom FileService

class DioHttpFileService extends FileService {
  Dio _dio;

  DioHttpFileService(this._dio);

  @override
  Future<FileServiceResponse> get(String url,
      {Map<String.String> headers}) async {
    Options options =
        Options(headers: headers ?? {}, responseType: ResponseType.stream);

    Response<ResponseBody> httpResponse =
        await _dio.get<ResponseBody>(url, options: options);

    returnDioGetResponse(httpResponse); }}Copy the code

Custom FileServiceResponse

class DioGetResponse implements FileServiceResponse {
  final DateTime _receivedTime = DateTime.now();
  Response<ResponseBody> _response;

  DioGetResponse(this._response);

  @override
  Stream<List<int>> get content => _response.data.stream;

  @override
  int get contentLength => _getContentLength();

  @override
  String get eTag => _response.headers['etag']? .first ??'1';

  @override
  String get fileExtension {
    var fileExtension = ' ';
    finalcontentTypeHeader = _response.headers[Headers.contentTypeHeader]? .first;if(contentTypeHeader ! =null) {
      final contentType = ContentType.parse(contentTypeHeader);
      fileExtension = mimeTypes[contentType.mimeType];
    }
    return fileExtension;
  }

  @override
  int get statusCode => _response.statusCode;

  @override
  DateTime get validTill {
    // Without a cache-control header we keep the file for a week
    var ageDuration = const Duration(days: 7);
    final controlHeader = _response.headers['cache-control']? .first;if(controlHeader ! =null) {
      final controlSettings = controlHeader.split(', ');
      for (final setting in controlSettings) {
        final sanitizedSetting = setting.trim().toLowerCase();
        if (sanitizedSetting == 'no-cache') {
          ageDuration = const Duration(a); }if (sanitizedSetting.startsWith('max-age=')) {
          var validSeconds = int.tryParse(sanitizedSetting.split('=') [1])??0;
          if (validSeconds > 0) {
            ageDuration = Duration(seconds: validSeconds); }}}}return _receivedTime.add(ageDuration);
  }

  int _getContentLength() {
    try {
      return int.parse( _response.headers[Headers.contentLengthHeader]? .first ??'1');
    } catch (e) {
      return - 1; }}}Copy the code

Method of use

Dependencies: flutter_cache_manager_dio: ^ 2.0.0Copy the code
var dio = Dio();
dio.interceptors.add(LogInterceptor(responseBody: false)); . CachedNetworkImage( cacheManager: DioCacheManager(dio), imageUrl: url, placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) => Container( child: Text('error',),),);Copy the code

Then you can use Dio’s interception features, such as adding and refreshing tokens, adding logs, and so on.

address

Github.com/xfans/flutt…