使用 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,则不会。
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()。
希望这对某人有所帮助,因为我花了一段时间!
我有一长串单元格,每个单元格都包含一个图像。
磁盘上的图片很大,因为它们用于应用程序中的其他内容,如壁纸等。
我熟悉对大型位图进行重采样并在不再需要时将其丢弃的正常 Android 过程。
但是,我觉得尝试在列表适配器中动态地对图像重新采样会很低效,因为一旦解码就缓存它们,否则一扔会产生很多线程,我将不得不设法取消不需要的图像等。
该应用程序的构建广泛使用了出色的 MVVMCross 框架。我正在考虑使用 MvxImageViews,因为它们可以从磁盘加载图像并轻松缓存它们。问题是,我需要在缓存它们之前对它们重新采样。
我的问题是,是否有人知道在 MVVMCross 中执行此操作的既定模式,或者对我如何实现它有任何建议?我需要自定义下载缓存插件吗?任何建议都会很棒:)
好的,我想我找到了答案。我不小心看到了旧的 MVVMCross 3.1 版本的 DownloadCache 插件/MvxLocalFileImageLoader。
克隆最新 (v3.5) 存储库后,我发现已添加此功能。本地文件现在被缓存并且可以在第一次加载时重新采样:)
MvxImageView 有一个 Max Height / Width setter 方法传播到它的 MvxImageHelper,后者又将它发送到 MvxLocalFileImageLoader。
需要注意的一件事是,仅当您从文件加载时才会发生重采样,如果您使用的是资源 ID,则不会。
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()。
希望这对某人有所帮助,因为我花了一段时间!