我正在尝试在 GridView.builder
中加载手机图库(带分页)小部件。
这是issue我已经使用 photo_manager
创建了包裹。
我得到了一些帮助,这让我想到了一个可能的解决方案(请参阅我对该问题的最后评论)。
我希望能够在不闪烁或白页的情况下加载 Assets 。
在 IOS 原生上它非常快速和流畅,我想在 Flutter 中实现同样的效果。
您会在上面的 github 链接中找到我编写的所有代码。我设法使用 Map
做到了这一点。对象在内存中,但我需要改进算法以使其不在 OOM 中。
想要的解决方案(一个或另一个):
GridView
中,与原生 IOS 一样快。 ,无论使用哪个包,它都在工作。 如果这还不够清楚,请告诉我,作为提醒,请查看我对此的最后一条评论 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.builder
如 future
param 如果它在内存中,你将立即获得 Assets ,否则像往常一样加载它。随意更改这些值并对其进行测试,它已经在我的 iPhone 中使用这些值进行了改进,但是如果您滚动得非常快,您仍然会像以前一样看到一点。
您可以添加
FadeTransition
在这种情况下,这将导致不难看的 UI。
关于flutter - 在没有 OOM 的情况下,在 Flutter 中像原生 IOS 一样快地加载手机图库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69607403/