Home > database >  Flutter Image.memory() loading animation with slow large files
Flutter Image.memory() loading animation with slow large files

Time:03-10

I am fetching an image from the gallery and displaying it in my cropper with Image.memory(). But sometimes (with large files) it takes a few seconds for the image to show. I want to show a loading animation but how do I detect when it is loading or finished? There is no loadingBuilder like for Image.network(). Any ideas?

final XFile? image = await _picker.pickImage(source: ImageSource.gallery);

Image.memory(_imageToCrop!)

CodePudding user response:

you can maintain an enum for this,

enum State {idle, loading, done ,error}

now,

State fetchState = State.idle

void fetch()async{
      setState((){
         fetchState = State.loading;
        });

     try{
      final XFile? image = await _picker.pickImage(source: 
            ImageSource.gallery);
      Image.memory(_imageToCrop!);

      setState((){
        fetchState = State.done;
      });

    }catch(e){
    setState((){
     fetchState = State.error;
     });
  }
}

Now use this states in your widget tree to show loader when state is loading.

you can use a single boolean variable as said in other answer but with this method you can catch errors at run time. You can use this method for api calls also.

CodePudding user response:

You should once check this documentation provided by flutter frame_builder. You could also use frameBuilder for your requirement.

May be my code will help you:-

import 'dart:typed_data';

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

void main() {
  runApp(const MaterialApp(
    title: 'Temp',
    home: const MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool loading = false;
  late Uint8List image;
  XFile? file = null;

  ImagePicker imagePicker = ImagePicker();

  Future<void> pickImage() async {
    print('starting');
    setState(() {
      loading = true;
    });

    file = await imagePicker.pickImage(source: ImageSource.gallery);
    print('file');
    if(file != null){
      print(file.toString());
      image = await file!.readAsBytes();
    }

    setState(() {
      loading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Image Picker'),
      ),
      body: loading
          ? Container(
              child: const Center(child: CircularProgressIndicator()),
            )
          : file != null?Container(child: Center(child: Image.memory(image),)) : Container(
            child: const Center(child: Text('Pick an Image')),
          ),
          floatingActionButton: FloatingActionButton(
            child: const Icon(
              Icons.image,
            ),
            onPressed: (){
              pickImage();
            }),
    );
  }
}

Short Description - my code will fetch an image from the system and then show … I have used a loading widget while the image is fetching and being converted to bytes.

It might be helpful if you share your logic here to figure out the main problem(if missing any thing).

  • Related