Watch the video (25 min)
On this page16 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. Why Bytes
  5. 2. Showing the Image
  6. 3. Hobbies With FilterChip
  7. 4. Copy the List When Editing
  8. 5. Save Everything
  9. 6. Show the Photo on the Dashboard
  10. Code Examples
  11. Common Beginner Mistakes
  12. Best Practices
  13. Mini Challenge
  14. Practice Questions
  15. Practice Answers
  16. Key Takeaways

Lecture 007 — Image Storage & Hobby Chips

Category4 — Images & Hobbies
Lecture007 of 007
Estimated video length25 min
TargetFlutter 3.44 · Dart 3.12 · hive 2.2
LevelBeginner
VideoPart 3 — Image Storage, Hobbies with FilterChip & ValueListenableBuilder
Source codeGitHub — urraan_hive_final_code

The last two fields of our model: a profile photo stored as bytes, and hobbies chosen with FilterChips and stored as a List<String>. Then the dashboard shows the photo in a round avatar.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways


Prerequisites

Lectures 001–006, and FilterChip, Wrap and DecorationImage from Essential Widgets.


Connection With Previous Lectures

The model already has profileImage (Uint8List?) and hobbies (List<String>). The form does not fill them yet. We add an image picker and chips, and the dashboard shows the result.


Learning Objectives

  • Pick an image with image_picker and read it as bytes
  • Store and show a Uint8List with MemoryImage
  • Build multi-select chips with FilterChip over a List<String>
  • Copy the list so editing does not change the saved record early
  • Show the avatar on the dashboard

1. Why Bytes

Hive cannot store a File path safely (the file may move or be cleared), but it can store Uint8List — the raw bytes. Picking returns an XFile; readAsBytes() gives the bytes.

dart
final imagePicker = ImagePicker();
Uint8List? _imageBytes;

Future<void> _pickImage(ImageSource source) async {
  final image = await imagePicker.pickImage(source: source);
  if (image == null) return;               // user cancelled
  final bytes = await image.readAsBytes();
  setState(() => _imageBytes = bytes);
}

ImageSource.gallery or ImageSource.camera. The null check handles a user who backs out.

2. Showing the Image

dart
Container(
  width: 200,
  height: 200,
  decoration: BoxDecoration(
    color: Colors.grey.shade200,
    borderRadius: BorderRadius.circular(15),
    image: _imageBytes != null
        ? DecorationImage(fit: BoxFit.cover, image: MemoryImage(_imageBytes!))
        : null,
  ),
  child: _imageBytes != null ? null : const Icon(Icons.image, size: 50),
)

MemoryImage turns bytes into an image provider. BoxFit.cover fills the box without stretching. When there is no image, an icon is the placeholder.

3. Hobbies With FilterChip

dart
final List<String> _hobbies = ['Cricket', 'Football', 'Hockey', 'Badminton'];
List<String> _selectedHobbies = [];
dart
Wrap(
  spacing: 8,
  children: [
    for (final hobby in _hobbies)
      FilterChip(
        label: Text(hobby),
        selected: _selectedHobbies.contains(hobby),
        onSelected: (selected) {
          setState(() {
            if (selected) {
              _selectedHobbies.add(hobby);
            } else {
              _selectedHobbies.remove(hobby);
            }
          });
        },
      ),
  ],
)

Wrap moves chips to the next line when the row is full. selected is true when the hobby is in the list; onSelected adds or removes it.

4. Copy the List When Editing

dart
_selectedHobbies = List.of(item.hobbies);

If you assign item.hobbies directly, tapping chips edits the saved record's list before you press Update. List.of makes a copy so changes only count when you save.

5. Save Everything

dart
final item = DataObjects()
  ..key = widget.item?.key ?? GeneralBox.getUniqueKey()
  ..name = controllerName.text.trim()
  ..address = controllerAddress.text.trim()
  ..profileImage = _imageBytes
  ..hobbies = _selectedHobbies;

6. Show the Photo on the Dashboard

In ListTile add a leading:

dart
leading: CircleAvatar(
  backgroundImage:
      item.profileImage != null ? MemoryImage(item.profileImage!) : null,
  child: item.profileImage == null ? const Icon(Icons.person) : null,
),

Code Examples

Example 1 — The Finished Form

The finished lib/screen_add_update_record.dart is in the course repository at app/lib/screen_add_update_record.dart. It is Lecture 006's screen plus the fields, picker, preview, chips, and the copy in initState.

Example 2 — Platform Setup for image_picker

  • iOS: add NSPhotoLibraryUsageDescription (and NSCameraUsageDescription for the camera) to ios/Runner/Info.plist.
  • Android: the gallery works without extra permissions on current Flutter; the camera uses the system camera app.
  • Web: works as a file chooser.

Common Beginner Mistakes

1. Not handling null from the picker — cancelling returns null; using it crashes.

2. Saving big photos — a full-resolution photo can be several MB per record, slowing the list. Reduce it: pickImage(source: ..., maxWidth: 600, imageQuality: 80).

3. Editing item.hobbies directly — copy with List.of (section 4).

4. Missing iOS usage description — the app closes the moment the picker opens.

5. context after await — if you ever call Navigator/ScaffoldMessenger after an await, check if (!mounted) return; first.


Best Practices

  • Resize images when picking (maxWidth, imageQuality).
  • Keep the list of hobbies in one constant list; later it can come from the box too.
  • Show a placeholder whenever the image is null.

Mini Challenge

Add a Remove photo button that sets _imageBytes = null, and a Camera button that uses ImageSource.camera.


Practice Questions

  1. Why bytes and not a file path? 2. What does readAsBytes return? 3. Why List.of in initState? 4. What stops the chips from overflowing the screen?

Practice Answers

  1. A path can break; bytes are stored inside the database itself.
  2. A Future<Uint8List>.
  3. So edits happen on a copy until the user saves.
  4. Wrap, which flows onto new lines.

Key Takeaways

  • Store images as Uint8List; show them with MemoryImage.
  • FilterChip + List<String> = multi-select; copy the list before editing.
  • You now have a complete Hive app: model, adapter, manager, live list, add/update, photo and hobbies.

Video lecture

Lecture 007 · 25 min