使用 MVVM Cross 为 Android 中的列表重新采样大位图

Resampling large bitmaps for lists in Android using MVVM Cross

我有一长串单元格,每个单元格都包含一个图像。

磁盘上的图片很大,因为它们用于应用程序中的其他内容,如壁纸等。

我熟悉对大型位图进行重采样并在不再需要时将其丢弃的正常 Android 过程。

但是,我觉得尝试在列表适配器中动态地对图像重新采样会很低效,因为一旦解码就缓存它们,否则一扔会产生很多线程,我将不得不设法取消不需要的图像等。

该应用程序的构建广泛使用了出色的 MVVMCross 框架。我正在考虑使用 MvxImageViews,因为它们可以从磁盘加载图像并轻松缓存它们。问题是,我需要在缓存它们之前对它们重新采样。

我的问题是,是否有人知道在 MVVMCross 中执行此操作的既定模式,或者对我如何实现它有任何建议?我需要自定义下载缓存插件吗?任何建议都会很棒:)

好的,我想我找到了答案。我不小心看到了旧的 MVVMCross 3.1 版本的 DownloadCache 插件/MvxLocalFileImageLoader。

克隆最新 (v3.5) 存储库后,我发现已添加此功能。本地文件现在被缓存并且可以在第一次加载时重新采样:)

MvxImageView 有一个 Max Height / Width setter 方法传播到它的 MvxImageHelper,后者又将它发送到 MvxLocalFileImageLoader。

需要注意的一件事是,仅当您从文件加载时才会发生重采样,如果您使用的是资源 ID,则不会。

来源在这里:https://github.com/MvvmCross/MvvmCross/blob/3.5/Plugins/Cirrious/DownloadCache/Cirrious.MvvmCross.Plugins.DownloadCache.Droid/MvxAndroidLocalFileImageLoader.cs

MVVMCross 再次拯救了我^_^

更新: 现在我实际上已经全部正常工作了,这里有一些提示:

  • 正如我在评论中指出的那样,本地图像缓存目前仅在 3.5.2 alpha MVVMCross 上可用。这与我的项目不兼容,因此我使用 3.5.1 创建了自己的 3.5.2a MvxImageView、MvxImageHelper 和 MvxAndroidLocalFileImageLoader 副本以及它们的接口,并在设置 class.

    中注册了它们
  • 我修改了 MvxAndroidLocalFileImageLoader 以重新采样资源,而不仅仅是文件。

  • 您必须使用此处记录的 "res:" 前缀绑定到 MvxImageView 的 ImageUrl 属性 (Struggling to bind local images in an MvxImageView with MvvmCross);如果绑定到 'DrawableId',这会将图像直接分配给底层 ImageView,并且不会发生缓存/重采样。

  • 我需要能够设置自定义 MvxImageview 的最大高度/宽度以进行重采样 布局为 inflated/bound 之后,但是 before 检索图像(我想在 'OnMeasure' 期间设置它们,但那时图像已经加载)。可能有更好的方法,但我修改了一个 bool 标志 'SizeSet'。如果这是错误的(即在初始绑定期间),图像 url 将被临时存储。一旦将其设置为 true(在 OnMeasure 之后),存储的 url 将传递给要加载的底层 ImageHelper。

  • 应用程序的一部分使用全屏图像作为寻呼机适配器中片段的背景。位图的垃圾收集速度不够快,导致在尝试加载下一张大图像时最终出现 OOM。当片段被销毁时手动调用 GC.Collect() 可以释放内存,但会导致 UI 卡顿,并且还会擦除缓存,因为它使用的是弱引用。

  • 在寻呼机适配器中的片段之间移动时,我经常在 Lollipop 上遇到 SIGSEGV 崩溃(它们从未在 KitKat 上发生过)。我设法通过将 SetImageBitmap(null) 添加到 ImageView 的 Dispose 方法来解决这个问题。然后,我在包含片段的 OnDestroyView() 的 ImageView 上调用 Dispose()。

希望这对某人有所帮助,因为我花了一段时间!