Search code examples
flutterdartasynchronousasync-awaitbackground-thread

Flutter: How can I run a function on background thread in dart


Future getImage() async {
 var image = await ImagePicker.pickImage(source: ImageSource.camera);
 setState(() {
   _image = image;
   print("IMG:" + _image.toString());
 });
 setPrefs() ;
}

Future setPrefs() async {
 _base64 = base64.encode(_image.readAsBytesSync());
 print(_base64);
 final prefs = await SharedPreferences.getInstance();
 prefs.setString(IMAGE_KEY, _base64);

}

The readAsBytesSync() method works fine on Android but too slow in iOS. So how can I move this code to a new background thread?


Solution

  • 1. Use Future

    You can use the async version of the readAsBytes.

    So instead of:

    final imageData = _image.readAsBytesSync();
    _base64 = base64.encode(imageData);
    

    You could have:

    final imageData = await _image.readAsBytes();
    _base64 = base64.encode(imageData);
    

    2. Use Isolate

    In your code, it may not necessarily be the readAsBytes line that is slow. It might be the base 64 encodings of the image. If that's the case, you could put the entire computation into a separate isolate. There is a convenient method compute that you can use.

    // This needs to be a global function
    encodeImage(File imageFile) {
        return base64.encodeimageFile.readAsBytesSync());
    }
    
    Future setPrefs() async {
     _base64 = await compute(encodeImage, _image);
     print(_base64);
     final prefs = await SharedPreferences.getInstance();
     prefs.setString(IMAGE_KEY, _base64);
    }
    

    In addition, it is worth mentioning that SharedPreferences (for Android, aka, NSUserDefaults on iOS) is designed to store small user settings. It is not designed for storing the images, which could be megabytes big. It is better to copy the image file into the app's document folder, and only store the filename in the SharedPreferences.