skip to Main Content

I tried CachedNetworkImage but it always reload when i switch page in CarouselSlider.

enter image description here

this my code:

// HeroBannerModel
class HeroBannerWidget extends StatefulWidget {
  final List<HeroBannerModel> heroBanner;
  const HeroBannerWidget({
    Key? key,
    required this.heroBanner,
  }) : super(key: key);

  @override
  _HeroBannerWidgetState createState() => _HeroBannerWidgetState();
}

class _HeroBannerWidgetState extends State<HeroBannerWidget> {
  int _current = 0;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _preCacheImages();
  }

  void _preCacheImages() {
    final _heroBanner = widget.heroBanner;
    if (_heroBanner.isEmpty) return;
    for (final item in _heroBanner) {
      precacheImage(NetworkImage(item.file.url.original), context);
    }
  }

  @override
  Widget build(BuildContext context) {
    final _heroBanner = widget.heroBanner;
    if (_heroBanner.isEmpty) return const SizedBox.shrink();

    return Stack(
      alignment: Alignment.center,
      children: [
        CarouselSlider(
          items: _heroBanner.map((item) {
            return GestureDetector(
              onTap: () async {
                final _link = item.link;
                if (_link == null) return;
                BaseUtils.launchURL(_link);
              },
              child: BaseImageView(
                url: item.file.url.original,
                width: size.width,
                fit: BoxFit.cover,
              ),
            );
          }).toList(),
          options: CarouselOptions(
            height: getSize(453),
            initialPage: 0,
            viewportFraction: 1,
            enableInfiniteScroll: false,
            onPageChanged: (index, reason) {
              setState(() {
                _current = index;
              });
            },
          ),
        ),
        Positioned(
          bottom: 4,
          child: AnimatedSmoothIndicator(
            activeIndex: _current,
            count: _heroBanner.length,
            effect: ExpandingDotsEffect(
              dotWidth: getSize(8.0),
              dotHeight: getSize(8.0),
              spacing: getSize(8.0),
              expansionFactor: getSize(12.0),
              dotColor: AppColor.greyV07,
              activeDotColor: AppColor.greyV09,
            ),
          ),
        ),
      ],
    );
  }
}

// BaseImageView
class BaseImageView extends StatelessWidget {
  ///[url] is required parameter for fetching network image
  final String? url;

  ///[imagePath] is required parameter for showing png,jpg,etc image
  final String? imagePath;

  ///[svgPath] is required parameter for showing svg image
  final String? svgPath;

  ///[file] is required parameter for fetching image file
  final File? file;

  final double? height;
  final double? width;
  final Color? color;
  final BoxFit? fit;
  final String placeHolder;
  final Alignment? alignment;
  final VoidCallback? onTap;
  final EdgeInsetsGeometry? margin;
  final BorderRadius? radius;
  final BoxBorder? border;

  ///a [BaseImageView] it can be used for showing any type of images
  /// it will shows the placeholder image if image is not found on network image
  const BaseImageView({
    super.key,
    this.url,
    this.imagePath,
    this.svgPath,
    this.file,
    this.height,
    this.width,
    this.color,
    this.fit,
    this.alignment,
    this.onTap,
    this.radius,
    this.margin,
    this.border,
    this.placeHolder = 'assets/images/img_not_found.png',
  });

  @override
  Widget build(BuildContext context) {
    return alignment != null
        ? Align(
            alignment: alignment!,
            child: _buildWidget(),
          )
        : _buildWidget();
  }

  Widget _buildWidget() {
    return Padding(
      padding: margin ?? EdgeInsets.zero,
      child: InkWell(
        onTap: onTap,
        child: _buildCircleImage(),
      ),
    );
  }

  ///build the image with border radius
  dynamic _buildCircleImage() {
    if (radius != null) {
      return ClipRRect(
        borderRadius: radius,
        child: _buildImageWithBorder(),
      );
    } else {
      return _buildImageWithBorder();
    }
  }

  ///build the image with border and border radius style
  Widget _buildImageWithBorder() {
    if (border != null) {
      return Container(
        decoration: BoxDecoration(
          border: border,
          borderRadius: radius,
        ),
        child: _buildImageView(),
      );
    } else {
      return _buildImageView();
    }
  }

  Widget _buildImageView() {
    if (svgPath != null && svgPath!.isNotEmpty) {
      return SizedBox(
        height: height,
        width: width,
        child: SvgPicture.asset(
          svgPath!,
          height: height,
          width: width,
          fit: fit ?? BoxFit.contain,
          color: color,
        ),
      );
    } else if (file != null && file!.path.isNotEmpty) {
      return Image.file(
        file!,
        height: height,
        width: width,
        fit: fit ?? BoxFit.cover,
        color: color,
      );
    } else if (url != null && url!.isNotEmpty) {
      return CachedNetworkImage(
        height: height,
        width: width,
        fit: fit,
        imageUrl: url!,
        color: color,
        cacheManager: BaseCustomCacheManager(),
        placeholder: (context, url) => SizedBox(
          height: 30,
          width: 30,
          child: LinearProgressIndicator(
            color: Colors.grey.shade200,
            backgroundColor: Colors.grey.shade100,
          ),
        ),
        errorWidget: (context, url, error) => Image.asset(
          placeHolder,
          height: height,
          width: width,
          fit: fit ?? BoxFit.cover,
        ),
      );
    } else if (imagePath != null && imagePath!.isNotEmpty) {
      return Image.asset(
        imagePath!,
        height: height,
        width: width,
        fit: fit ?? BoxFit.cover,
        color: color,
      );
    }

    return Image.asset(
      placeHolder,
      height: height,
      width: width,
      fit: fit ?? BoxFit.cover,
      color: color,
    );
    // return const SizedBox();
  }
}

// BaseCustomCacheManager
class BaseCustomCacheManager extends CacheManager with ImageCacheManager {
  static const String key = "customCache";

  static BaseCustomCacheManager? _instance;

  BaseCustomCacheManager._()
      : super(
          Config(
            key,
            stalePeriod: const Duration(days: 30),
            maxNrOfCacheObjects: 1000,
            repo: JsonCacheInfoRepository(databaseName: key),
            fileSystem: IOFileSystem(key),
            fileService: HttpFileService(),
          ),
        );

  factory BaseCustomCacheManager() {
    return _instance ??= BaseCustomCacheManager._();
  }
}

// IOFileSystem
class IOFileSystem implements c.FileSystem {
  final Future<Directory> _fileDir;

  IOFileSystem(String key) : _fileDir = createDirectory(key);

  static Future<Directory> createDirectory(String key) async {
    var baseDir = await getTemporaryDirectory();
    var path = p.join(baseDir.path, key);

    var fs = const LocalFileSystem();
    var directory = fs.directory((path));
    await directory.create(recursive: true);
    return directory;
  }

  @override
  Future<File> createFile(String name) async {
    return (await _fileDir).childFile(name);
  }
}

I’d like it to display images, no loading like a gif file.
Please help me. i tried many different way to fix this but i can’t

2

Answers


  1. Chosen as BEST ANSWER

    I tried to understand it, and it seems to be caused by the large size and high resolution of the image. However, I used CachedNetworkImage and here is my solution.

    // preCacheImages
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        _preCacheImages();
      }
    
      void _preCacheImages() {
        final _heroBanner = widget.heroBanner;
        if (_heroBanner.isEmpty) return;
        for (final item in _heroBanner) {
          precacheImage(NetworkImage(item.file.url.original), context);
        }
      }
    
    
    // CachedNetworkImage by using default its cacheManger
    // maxWidthDiskCache: 1000,
    // maxHeightDiskCache: 1000,
    CachedNetworkImage(
            height: height,
            width: width,
            fit: fit,
            imageUrl: url!,
            color: color,
            maxWidthDiskCache: 1000,
            maxHeightDiskCache: 1000,
            useOldImageOnUrlChange: true,
            // cacheManager: BaseCustomCacheManager(),
            placeholder: (context, url) => SizedBox(
              height: 30,
              width: 30,
              child: LinearProgressIndicator(
                color: Colors.grey.shade200,
                backgroundColor: Colors.grey.shade100,
              ),
            ),
            errorWidget: (context, url, error) => Image.asset(
              placeHolder,
              height: height,
              width: width,
              fit: fit ?? BoxFit.cover,
            ),
          );
    

    I don't know this correct one but it works!


  2. First of all replace this

    @override
    void didChangeDependencies() {
      super.didChangeDependencies();
      _preCacheImages();
    }
    

    with

    @override
    void initState() {
      _preCacheImages();
      super.initState();
    }
    

    And your main build method

    Remove below code

    final _heroBanner = widget.heroBanner;
    if (_heroBanner.isEmpty) return const SizedBox.shrink();
    

    and you can set condition like

    return _heroBanner.isEmpty ? const SizedBox.shrink() : Stack(
          alignment: Alignment.center,
          ..
          ..
          ..
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search