【问题标题】:Saving ImagePicker image from gallery in Flutter在 Flutter 中从图库中保存 ImagePicker 图像
【发布时间】:2020-11-06 16:21:08
【问题描述】:

与往常一样,这些最简单的解决方案对我来说是最难解决的。我有 ImagePicker 函数可以从图库中获取图像并将其设置为背景。下面的代码完美运行,但图像没有保存,所以每次重新启动后,它都不存在。代码如下:

Future _getImage() async {
final picker = ImagePicker();

final pickedFile = await picker.getImage(source: ImageSource.gallery);

setState(() {
  if (pickedFile != null) {
    _image = File(pickedFile.path);

    print('_image: $_image');
  } else {
    print('No image selected');
  }
});

}

所以我的问题是如何将图像保存为永久并在重新启动后持续存在,我已经尝试了所有方法(设置和保存路径等),但由于某种原因无法使其正常工作。希望解决方案很简单。我的理解是它应该保存到设备的本地存储中,在这种情况下是模拟器,但它当然应该适用于每台设备。

【问题讨论】:

  • 它在设备的本地存储中,只是不在应用程序的缓存本地存储中。我建议你看看你可以用 CacheManager 做什么。我没有这些问题,因为我将挑选的图像存储在 Firebase 上,然后使用 CachedNetworkImage 下载并显示它们。该小部件在幕后使用 CacheManager。

标签: flutter dart


【解决方案1】:

您可以将用户从图库中挑选的图像保存到应用程序目录。然后,使用此图像从本地存储中显示。

  1. 使用path_provider获取目录路径

    Directory appDocDir = await getApplicationDocumentsDirectory();
    String appDocPath = appDocDir.path;
    
  2. 保存图片到你的目录

    final picker = ImagePicker();
    
    final pickedFile = await picker.getImage(source: ImageSource.gallery);
    
    if (pickedFile == null) return;
    
    _image = File(pickedFile.path);
    
    final fileName = 'background_image';
    final File localImage = await _image.copy('${widget.appDocPath}/$fileName');
    
  3. 在小部件树中使用图像

    Image image;
    var hasLocalImage =
        File('${widget.appDocPath}/background_image').existsSync();
    if (hasLocalImage) {
      var bytes =
          File('${widget.appDocPath}/background_image').readAsBytesSync();
      image = Image.memory(bytes);
    }
    

完整的工作示例:

import 'dart:io';

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
        // This makes the visual density adapt to the platform that you run
        // the app on. For desktop platforms, the controls will be smaller and
        // closer together (more dense) than on mobile platforms.
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: SplashScreen(),
    );
  }
}

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  String appDocPath;

  Future<void> getApplicationDirectoryPath() async {
    Directory appDocDir = await getApplicationDocumentsDirectory();
    appDocPath = appDocDir.path;
  }

  @override
  initState() {
    getApplicationDirectoryPath().then((_) {
      Navigator.pushReplacement(
          context,
          MaterialPageRoute(
              builder: (BuildContext context) => Home(
                    appDocPath,
                  )));
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

class Home extends StatefulWidget {
  final String appDocPath;

  Home(this.appDocPath);
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  File _image;

  @override
  initState() {
    super.initState();
  }

  Future _getImage() async {
    final picker = ImagePicker();

    final pickedFile = await picker.getImage(source: ImageSource.gallery);

    if (pickedFile == null) return;

    _image = File(pickedFile.path);

    final fileName = 'background_image';
    final File localImage = await _image.copy('${widget.appDocPath}/$fileName');


    setState(() {
    });
  }

  @override
  Widget build(BuildContext context) {
    Image image;
    var hasLocalImage =
        File('${widget.appDocPath}/background_image').existsSync();
    if (hasLocalImage) {
      var bytes =
          File('${widget.appDocPath}/background_image').readAsBytesSync();
      image = Image.memory(bytes);
    }

    return new Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            _getImage();
          },
        ),
        body: (File('${widget.appDocPath}/background_image').existsSync())
            ? Center(
                child: image,
              )
            : Text('NO PICTURE HAS BEEN SELECTED NOW OR IN THE PAST'));
  }
}

【讨论】:

    【解决方案2】:

    可能有更好的方法来做到这一点,但这里有一个使用 shared preferences 的工作示例:

    import 'dart:io';
    
    import 'package:flutter/material.dart';
    import 'package:image_picker/image_picker.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    
    void main() async {
      runApp(MaterialApp(debugShowCheckedModeBanner: false, home: MyApp()));
    }
    
    class MyApp extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
    
      String filePath = '';
    
      getImage() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        bool check = prefs.containsKey('image');
        if (check) {
          setState(() {
            filePath = prefs.getString('image');
          });
          return;
        }
        ImagePicker imagePicker = new ImagePicker();
        PickedFile image = await imagePicker.getImage(source: ImageSource.gallery);
        String imagePath = image.path;
        await prefs.setString('image', imagePath);
        setState(() {
          filePath = prefs.getString('image');
        });
      }
    
      @override
      void initState() {
        super.initState();
        getImage();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: Container(
            child: filePath == '' ? FlatButton(
              onPressed: getImage,
              child: Text('get image'),
            ) : Image.file(File(filePath)),
          )
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 2017-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多