在颤振插件 image_picker 示例中从图库中选择图像时内存增加

Posted

技术标签:

【中文标题】在颤振插件 image_picker 示例中从图库中选择图像时内存增加【英文标题】:Memory increase when pick image from gallery in example of flutter plugin image_picker 【发布时间】:2020-01-13 21:06:44 【问题描述】:

我运行flutter的插件image_picker的示例。

当我从画廊中一张一张地挑选图像时,内存不断增加。理想情况下是memory should jump back,因为在这个示例应用中它是at most select one image

class _MyHomePageState extends State<MyHomePage> 
  File _imageFile;              <-- this one keep the file of selected image.
  dynamic _pickImageError;
  bool isVideo = false;
  VideoPlayerController _controller;
  String _retrieveDataError;

  void _onImageButtonPressed(ImageSource source) async 
    ...
    try 
      _imageFile = await ImagePicker.pickImage(source: source);  <--- how to set value
      setState(() );
     catch (e) 
      _pickImageError = e;
    
    ...
  

  @override
  Widget build(BuildContext context) 
    ...
    Image.file(_imageFile);   <-- how to use it to display UI.
    ...
  

我的问题是dispose the resource使用的File如何?

【问题讨论】:

pickImage() 现在已弃用。使用 getImage()..Flutter ImagePicker Example 【参考方案1】:

您可以使用ImagePickermaxHeightmaxWidth 参数来加载调整大小的图像。

例如

var image = await ImagePicker.pickImage(source: ImageSource.gallery, maxWidth: 600);

另外,如果你想显示或保存到文件系统,你可以使用FlutterNativeImage插件(内部使用ImagePicker插件),它采用图像路径和压缩值来压缩图像。

例如

var compressedImage = await FlutterNativeImage.compressImage(image.path, quality: 50);

参考:https://github.com/btastic/flutter_native_image

【讨论】:

我的问题是为什么在演示项目中内存不断增加。 因为您正在将位图加载到内存中,该位图的大小/像素可能更大。在加载到内存之前,您需要先压缩/调整图像大小。 When pick another image, the image object is released, the memory should reduce back.但它一直在增加。 Dart VM 发起 GC 后,内存将被释放。 我在演示项目中做同样的选择视频,每次选择视频时内存都会减少。【参考方案2】:

仅仅选择File 不会影响内存,因为File 只是一个引用,并不保存文件系统实体的实际字节。但是,从文件中创建 Image 会增加内存使用量,因为 Image 保存了它引用的 File 的所有字节(一旦它读取了所有字节)。

根据您目前分享的内容,我们无法判断这是否是代码问题。除非您一次维护对超过 1 个 Image 的引用,否则您的应用将使用的最小内存应该反映该图像的大小。我说 minimum 是因为垃圾收集不会过于激进,并且不会在您不再引用它时立即处理所有内容。只有当它知道它需要运行 GC 时才会运行 GC,这样应用程序不会被饿死并且操作系统也很高兴。我不知道这是否适用于 Flutter,但是对于原生 android,它还取决于制造商对 Android OS 的定制,它可以要求应用程序以各种频率进行 GC。

在内存分配清晰可见的用例中,只需在加载第二张图像后点击 GC 按钮即可。如果内存下降到与加载单个图像相同的水平,那么一切都很好。如果没有,您可能会在代码中的某处维护对这些图像的意外引用。

原生 Android 也有这个奇怪的东西(可能取决于版本/制造商) - 这在一些较旧的三星设备上最为明显 - 最后 4 个位图被缓存并且您无法清除该缓存,并且取决于您必须处理的位图大小,该缓存可能占用了应用程序的几乎所有可用内存,并且您最终会遇到 OOM 错误......希望 Flutter 不会这样做,或者允许开发人员控制它。

【讨论】:

以上是关于在颤振插件 image_picker 示例中从图库中选择图像时内存增加的主要内容,如果未能解决你的问题,请参考以下文章

在颤振应用程序中添加 image_picker 插件后,Gradle Build 失败

在flutter中从image_picker包中打开相机会导致真实设备上的应用程序崩溃,但在模拟器(android)中运行良好

颤振 - 使用 image_picker 处理方法调用和 already_active 异常

为颤振添加 image_picker 依赖项时出错(iOS)

运行 image_picker 时我的新 android 应用程序崩溃(基于颤振飞镖)

Flutter从相册选择图片和相机拍照(image_picker)