Требуется ли кэширование изображения на веб-сайте? - PullRequest
2 голосов
/ 13 апреля 2020

Из-за того, что CachedNetworkImage не работает на флаттере, при портировании я пытался использовать это, но мой вопрос: действительно ли нам это нужно? Или мы просто используем изображение. Сеть, а также браузер и работник сервиса будут обрабатывать часть кэша (которая затем задается заголовком ответа сервера, например, cache-control = "max-age = 43200, publi c"

Это используется в проекте доставки еды, над которым я работаю, https://www.santaiyamcha.com

Ниже приведены классы, которые я использую для замены CachedNetworkImage, который, кажется, не работает хорошо.

import 'package:flutter/material.dart';
import 'package:http/http.dart';

import 'package:http_extensions_cache/http_extensions_cache.dart';
import 'package:http_extensions/http_extensions.dart';

/// Builds a widget when the connectionState is none and waiting
typedef LoadingBuilder = Widget Function(BuildContext context);

/// Builds a if some error occurs
typedef ErrorBuilder = Widget Function(BuildContext context, Object error);

class MeetNetworkImage extends StatelessWidget {
  /// Image url that you want to show in your app.
  final String imageUrl;

  /// When image data loading from the [imageUrl],
  /// you can build specific widgets with [loadingBuilder]
  final LoadingBuilder loadingBuilder;

  /// When some error occurs,
  /// you can build specific error widget with [errorBuilder]
  final ErrorBuilder errorBuilder;

  final double scale;

  final double width;
  final double height;
  final Color color;

  final FilterQuality filterQuality;

  final BlendMode colorBlendMode;

  final BoxFit fit;
  final AlignmentGeometry alignment;

  final ImageRepeat repeat;

  final Rect centerSlice;
  final bool matchTextDirection;

  /// Whether to continue showing the old image (true), or briefly show nothing
  /// (false), when the image provider changes.
  final bool gaplessPlayback;

  final String semanticLabel;
  final bool excludeFromSemantics;

  MeetNetworkImage({
    @required this.imageUrl,
    this.loadingBuilder = null,
    this.errorBuilder = null,
    this.scale = 1.0,
    this.height,
    this.width,
    this.color = const Color(0xFDFFFF),
    this.fit = BoxFit.fill,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.semanticLabel,
    this.centerSlice,
    this.colorBlendMode,
    this.excludeFromSemantics = false,
    this.filterQuality = FilterQuality.low,
    this.matchTextDirection = false,
    this.gaplessPlayback = false,
  })  : assert(imageUrl != null),
        assert(alignment != null),
        assert(repeat != null),
        assert(matchTextDirection != null);

  Future<Response> getUrlResponse() {
    /*
    //The caching part  I tried, does not seems working
    final client = ExtendedClient(
      inner: Client(),
      extensions: [
        CacheExtension(
          //logger: Logger("Cache"),
          defaultOptions: CacheOptions(
            expiry: const Duration(hours: 168),
            // The duration after the cached result of the request will be expired.
            //forceUpdate: false, // Forces to request a new value, even if an valid cache is available
            //forceCache: false, // Forces to return the cached value if available (even if expired).
            //ignoreCache: true, //Indicates whether the request should bypass all caching logic
            //returnCacheOnError: true, //If [true], on error, if a value is available in the  store if is returned as a successful response (even if expired).
            keyBuilder: (request) => "${request.method}_${imageUrl.toString()}",
            // Builds the unqie key used for indexing a request in cache.
            store: MemoryCacheStore(),
            // The store used for caching data.
            shouldBeSaved: (response) =>
                response.statusCode >= 200 && response.statusCode < 300,
          ),
        )
      ],
    );

    return client.get(imageUrl);
     */
    return get(imageUrl);
  }

  Widget getLoadingWidget(BuildContext context) {
    if (loadingBuilder != null) {
      return loadingBuilder(context);
    } else
      return Container(
          height: height, width: width,
          child: Center(
            child: CircularProgressIndicator()
          )
          /*Image.asset(
          'assets/img/loading4.gif',
          height: height,
          width: width,
          fit: BoxFit.contain,
        ),*/
          );
  }

  Widget getErrorWidget(BuildContext context, String error) {
    if (errorBuilder != null) {
      return errorBuilder(context, error);
    } else
      return Center(child: Icon(Icons.error));
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: getUrlResponse(),
      builder: (BuildContext context, AsyncSnapshot<Response> snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.none:
          case ConnectionState.waiting:
            return getLoadingWidget(context);
          case ConnectionState.active:
          case ConnectionState.done:
            if (snapshot.hasError)
              return getErrorWidget(context, snapshot.error);
            if (!snapshot.hasData)
              return getErrorWidget(context, snapshot.error);
            //return getLoadingWidget(context);
            return Image.memory(
              snapshot.data.bodyBytes,
              scale: scale,
              height: height,
              width: width,
              color: color,
              fit: fit,
              alignment: alignment,
              repeat: repeat,
              centerSlice: centerSlice,
              colorBlendMode: colorBlendMode,
              excludeFromSemantics: excludeFromSemantics,
              filterQuality: filterQuality,
              gaplessPlayback: gaplessPlayback,
              matchTextDirection: matchTextDirection,
              semanticLabel: semanticLabel,
            );
        }
        return Container();
      },
    );
  }
}

Что вы предлагаете?

...