1

I want to store store an image in the localDB of the app and am using Hive. But I can't find any example where we can store a file using Uint8List locally with Hive. I can persist primitive data types like String, int etc with Hive but am unable to store any thing like images etc in bytes using Hive although it promises to do so. I can't find any example for the same.

padaleiana
  • 955
  • 1
  • 14
  • 23
Sahil Singh
  • 113
  • 4
  • 11

3 Answers3

2

I was able to accomplish this on Flutter Web for thumbnails in my app using Hive like so:

In My Hive Service

  static const _thumbnailsKey = 'thumbnails';
  static late Box<List<int>> _thumbnailsBox;

  HiveService._();

  static Future<void> initialize() async {
    await Hive.initFlutter();

    _thumbnailsBox = await Hive.openBox(_thumbnailsKey);
  }

  static Future<void> addThumbnailData({
    required String key,
    required List<int> data,
  }) async {
    await _thumbnailsBox.put(key, data);
  }

  static Uint8List getThumbnailData({required String key}) {
    final bytes = _thumbnailsBox.get(key);

    if (bytes == null) return Uint8List.fromList([]);

    return Uint8List.fromList(bytes);
  }

My Image Downloader Service

import 'dart:typed_data';

import 'package:http/http.dart' as http;

class ImageService {
  ImageService._();

  static Future<Uint8List> getImageData(String url) async {
    Uri uri = Uri.parse(url);

    final response = await http.get(uri);

    return response.bodyBytes;
  }
}

In My Widget's ViewModel (or anywhere you like)

I'm using GetX so I update my Image widget with _imageData.value = ...

  Future<void> _getThumbnailData() async {
    final cachedThumbnailData = HiveService.getThumbnailData(key: 'someKey');

    // This is where the magic happens
    if (cachedThumbnailData.isNotEmpty) {
      _imageData.value = cachedThumbnailData;
      return;
    }

    // Otherwise fetch the image data
    // In my case it's from a url
    final imageData = await ImageService.getImageData(thumbnailUrl);

    if (imageData.isEmpty) return;

    // Update Hive for the next time you need the image
    // You could also put this wherever you fetch your images
    await HiveService.addThumbnailData(
      key: reactionReportGroup.timestampNameKey,
      data: imageData,
    );

    _imageData.value = imageData;
  }

Now you can use either MemoryImage(_viewModel.imageData) or Image.memory(_viewModel.imageData)

Caleb Lindsey
  • 91
  • 1
  • 4
0

Don't. Save images as files in disk and store its name into database.

DiyorbekDev
  • 706
  • 1
  • 5
  • 19
0
    //Variables
    List? image = [];
    List? pickedImages;
    List imagesAsBytes = [];//List of images converted to bytes
    ImagesToSend imageObj = ImagesToSend(); //New instance of my HiveObject

    //Picking images    
    Future pickImage() async {
    setState(() {});
    final pickedImages = await ImagePicker().pickMultiImage();
//You can change .pickMultiImage() to pickImage(source: ImageSource.camera) if you want it direct from the camera or pickImage(source: ImageSource.gallery) if you want from the the gallery
    if (pickedImages == null) return;
    image!.addAll(pickedImages);
    setState(() => this.image = image);

    //Saving in Hive
    if (image == null) return;
imagesAsBytes = [];
for (var i in image!) {
  File file = File(i.path);
  imagesAsBytes.add(file.readAsBytesSync());
}
imageObj.images = imagesAsBytes;
boxImg.put('images_box', imageObj);
this.imagesAsBytes = boxImg.get('images_box').images;
  }

//###############################################################
//My Model
//This is a Hive object that holds the images
//I have this as a different dart file, hopefully, you know what this is
@HiveType(typeId: 0)
class ImagesToSend extends HiveObject {
  @HiveField(0)
  List<Uint8List>? images;
}
//############################################################
//Don't forget to have the hive adapter and the box open on your main dart file
 void main(List<String> args) async {
  await Hive.initFlutter();
  Hive.registerAdapter(ImagesToSendAdapter());
  boxImg = await Hive.openBox<ImagesToSend>('images_box');

  runApp(const MyApp());
}

This is my solution but I'm still facing issues. The images are being displayed but, if I close the app, hive will still holds them, but it dosen't display them anymore! If you can figure this part out, let me know ...lol

Jacob Athias
  • 67
  • 1
  • 6
  • I think this answer is maybe better as an edit to the question, rather than an answer... as it doesn't fully solve the problem. What do you think? – Karolina Hagegård Sep 16 '22 at 17:01