flutter - 在没有 OOM 的情况下,在 Flutter 中像原生 IOS 一样快地加载手机图库

标签 flutter dart flutter-image flutter-gridview

我正在尝试在 GridView.builder 中加载手机图库(带分页)小部件。
这是issue我已经使用 photo_manager 创建了包裹。
我得到了一些帮助,这让我想到了一个可能的解决方案(请参阅我对该问题的最后评论)。
我希望能够在不闪烁或白页的情况下加载 Assets 。
在 IOS 原生上它非常快速和流畅,我想在 Flutter 中实现同样的效果。
您会在上面的 github 链接中找到我编写的所有代码。我设法使用 Map 做到了这一点。对象在内存中,但我需要改进算法以使其不在 OOM 中。
想要的解决方案(一个或另一个):

  • 一个简单的方法是,将手机图库加载到 GridView 中,与原生 IOS 一样快。 ,无论使用哪个包,它都在工作。
  • 我目前糟糕的算法的改进,例如将 15 个 Assets 保留在当前 Assets 之上,15 个 Assets 在内存中,并且在滚动期间,不断更新这些值以移动列表中当前位置周围的范围。

  • 如果这还不够清楚,请告诉我,作为提醒,请查看我对此的最后一条评论 issue .

    最佳答案

    您可以使用这样的逻辑:

    final Map<String, Uint8List?> _cachedMap = {};
    void precacheAssets(int index) async {
        // Handle cache before index
        for (int i = max(0, index - 50); i < 50; i++) {
          getItemAtIndex(i);
        }
        // Handle cache after index
        for (int i = min(assetsList.length, index + 50); i < 50 + min(assetsList.length, index + 50); i++) {
          getItemAtIndex(i);
        }
        _cachedMap.removeWhere((key, value) {
          int currIndex = assetsList.indexWhere((element) => element.id == key);
          return currIndex < index - 50 && currIndex > index + 50;
        });
      }
      /// Get the asset from memory or fetch it if it doesn’t exist yet.
      /// Called in the builder method to display assets, not to precache them.
      Future<Uint8List?> getItemAtIndex(int index) async {
        AssetEntity entity = assetsList[index];
        if (_cachedMap.containsKey(entity.id)) {
          return _cachedMap[entity.id];
        }
        else {
          Uint8List? thumb = await entity.thumbDataWithOption(
              ThumbOption.ios(
                  width: width,
                  height: height,
                  deliveryMode: DeliveryMode.highQualityFormat,
                  quality: 90));
          _cachedMap[entity.id] = thumb;
          return thumb;
        }
      }
    
    您可以调用 precacheAssets您的 GridView.builder 中的方法在特定索引处,例如 if (index % 25 == 0)这将告诉每 25 个项目,将 50 个下一个项目放入缓存中,以便将 25 个项目添加到现有缓存中。
    另外,请调用 getItemAtIndex在您的 Future.builderfuture param 如果它在内存中,你将立即获得 Assets ,否则像往常一样加载它。
    随意更改这些值并对其进行测试,它已经在我的 iPhone 中使用这些值进行了改进,但是如果您滚动得非常快,您仍然会像以前一样看到一点。
    您可以添加 FadeTransition在这种情况下,这将导致不难看的 UI。

    关于flutter - 在没有 OOM 的情况下,在 Flutter 中像原生 IOS 一样快地加载手机图库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69607403/

    相关文章:

    flutter - 如何在 Flutter 中设置 AppBar 操作按钮颜色

    ios - Flutter 推送通知 : Unable to receive notifications in background or when app is closed

    google-chrome - 将 Dart VM 作为 Chrome NaCl 插件提供有多难?

    flutter - 从图库/相机取消图像选择器时出现Image.path错误

    flutter - 如何获得不同的列表

    flutter 构建错误。 flutter webview 插件的问题

    dart:调试 dart 客户端和现有 REST API 的客户端/服务器通信?

    firebase - 试用期机制 - Flutter/Firebase

    flutter - 如何在现有页面的顶部显示图像预览?

    flutter - 如何在 flutter 中以两种不同尺寸保存图像选择器中的图像