1

I have a list of base64 images comes from server and I have a class to cache them in temporary folder.

Because caching process may take some time, images not showing in UI specially when image is large .

I have a loading property in my model class and at first is true and when caching process finished it become false.

This is my cache model class:

class ImageCaching {
  int timestamp;
  String base64;
  File tempFile;
  bool loading;
  ImageCaching({this.base64, this.timestamp, this.loading = true}) {
    this.createTempFile();
  }

  createTempFile() async {
    Uint8List bytes = base64Decode(this.base64);
    final appDir = await getTemporaryDirectory();
    File file = File('${appDir.path}/${this.timestamp}.jpg');
    await file.writeAsBytes(bytes);
    this.tempFile = file;
    this.loading = false;
  }
}

This is where I show Image:

return imageCache.loading
          ? Text('Loading')
          : imageCache.tempFile != null
              ? Image.file(imageCache.tempFile)
              : Image.asset(
                  defaultImg,
                  fit: boxFit,
                );

This is my model class for my list:

class Image {
  int timestamp;
  String base64;
  ImageCaching imageCache;
  Image({
    @required this.timestamp,
    this.base64,
  }) {
    this.imageCache =
        this.base64 != null ? ImageCaching(base64: this.base64, timestamp: this.timestamp) : null;
  }
}

and I have a list of this class in redux store. and item to it.

But sometimes depends on image size, images not showing in UI and loading text, shows even caching finished.

I want to update UI after loading property become false.

I try using ChangeNotifier and it works, but I don't think this is a good way:

Caching model rewrite this ChangeNotifier:

class ImageCaching with ChangeNotifier {
  int timestamp;
  String base64;
  File tempFile;
  bool loading;
  ImageCaching({this.base64, this.timestamp, this.loading = true}) {
    this.createTempFile();
  }

  createTempFile() async {
    Uint8List bytes = base64Decode(this.base64);
    final appDir = await syspaths.getTemporaryDirectory();
    File file = File('${appDir.path}/${this.timestamp}.jpg');
    await file.writeAsBytes(bytes);
    this.tempFile = file;
    this.loading = false;
    notifyListeners();
  }
}

and in widget I try this:

image.imageCache?.addListener(() {
  setState(() {});
});

I think I can have memory problem in large list and weak phone.

As in doc said:

ChangeNotifier is optimized for small numbers (one or two) of listeners. It is O(N) for adding and removing listeners and O(N²) for dispatching notifications (where N is the number of listeners).

I will remove listener after loading become false.

BeHappy
  • 3,705
  • 5
  • 18
  • 59

0 Answers0