Avr*_*hom 11 c# android image out-of-memory xamarin.forms
有没有人尝试使用包含图像视图的ItemTemplate的A Xamarin.Forms Listview?现在,当ListView包含大约20行或更多行时会发生什么?
至于我,我有一个大约4K大小的.png文件加载到图像视图中.在使用OutOfMemoryError崩溃应用程序之前,最多显示9到12行.在Android Manifest中请求大堆之后,应用程序在60-70行之后崩溃.
我知道Xamarin正在推广使用BitmapFactory类来缩小位图,但这不适用于Xamarin Forms Image View(开箱即用).
我正试图摆弄ImageRenderer的Sub Class,看看我是否可以添加一个BitmapFactory.Options属性,如果这样可以解决问题.
此外,我可能需要检查Xamarin.Forms是否在ViewCell滚动屏幕后处理(回收)包含的位图.
在开始这个旅程之前,我非常希望得到任何可以使这个更简单或更简单的解决方案的评论,认为这个过程是不必要的.
期待...
Avr*_*hom 10
是的,我找到了解决方案.代码要遵循.但在此之前,让我解释一下我所做的一切.
所以,绝对需要掌握maters来处理图像及其底层资源(位图或可绘制,但是你想要调用它).基本上,它归结为处理原生的'ImageRenderer'对象.
现在,无法从任何地方获取对该ImageRenderer的引用,因为为了这样做,需要能够调用Platform.GetRenderer(...).由于其范围被声明为"内部",因此无法访问"平台"类.
所以,除了对Image类和它的(Android)Renderer进行子类化并从内部销毁这个Renderer本身(传递'true'作为参数时,我别无选择.不要尝试使用'false').在渲染器内部,我挂钩到页面消失(如果是TabbedPage).在大多数情况下,页面中消失事件将不会达到目的很好,比如当页面仍然在屏幕堆栈,但消失由于另一页上正在绘制顶部它.如果丢弃图像,则当页面再次被覆盖(显示)时,它将不会显示图像.在这种情况下,我们必须挂钩主导航页面的'Popped'事件.
我试图尽我所能地解释.其余的 - 我希望 - 你将能够从代码中获得:
这是PCL项目中的图像子类.
using System;
using Xamarin.Forms;
namespace ApplicationClient.CustomControls
{
public class LSImage : Image
{
}
}
Run Code Online (Sandbox Code Playgroud)
以下代码位于Droid项目中.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using Android.Util;
using Application.Droid.CustomControls;
using ApplicationClient.CustomControls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ApplicationClient.CustomControls.LSImage), typeof(LSImageRenderer))]
namespace Application.Droid.CustomControls
{
public class LSImageRenderer : ImageRenderer
{
Page page;
NavigationPage navigPage;
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
if (GetContainingViewCell(e.NewElement) != null)
{
page = GetContainingPage(e.NewElement);
if (page.Parent is TabbedPage)
{
page.Disappearing += PageContainedInTabbedPageDisapearing;
return;
}
navigPage = GetContainingNavigationPage(page);
if (navigPage != null)
navigPage.Popped += OnPagePopped;
}
else if ((page = GetContainingTabbedPage(e.NewElement)) != null)
{
page.Disappearing += PageContainedInTabbedPageDisapearing;
}
}
}
void PageContainedInTabbedPageDisapearing (object sender, EventArgs e)
{
this.Dispose(true);
page.Disappearing -= PageContainedInTabbedPageDisapearing;
}
protected override void Dispose(bool disposing)
{
Log.Info("**** LSImageRenderer *****", "Image got disposed");
base.Dispose(disposing);
}
private void OnPagePopped(object s, NavigationEventArgs e)
{
if (e.Page == page)
{
this.Dispose(true);
navigPage.Popped -= OnPagePopped;
}
}
private Page GetContainingPage(Xamarin.Forms.Element element)
{
Element parentElement = element.ParentView;
if (typeof(Page).IsAssignableFrom(parentElement.GetType()))
return (Page)parentElement;
else
return GetContainingPage(parentElement);
}
private ViewCell GetContainingViewCell(Xamarin.Forms.Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(ViewCell).IsAssignableFrom(parentElement.GetType()))
return (ViewCell)parentElement;
else
return GetContainingViewCell(parentElement);
}
private TabbedPage GetContainingTabbedPage(Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(TabbedPage).IsAssignableFrom(parentElement.GetType()))
return (TabbedPage)parentElement;
else
return GetContainingTabbedPage(parentElement);
}
private NavigationPage GetContainingNavigationPage(Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(NavigationPage).IsAssignableFrom(parentElement.GetType()))
return (NavigationPage)parentElement;
else
return GetContainingNavigationPage(parentElement);
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我将名称空间中的应用程序名称更改为PCL项目中的"ApplicationClient"和Droid项目中的"Application.Droid".您应该将其更改为您的应用名称.
此外,Renderer类末尾的几个递归方法,我知道我可以将它组合成一个Generic方法.问题是,当需要出现时,我一次建立一个.所以,这就是我离开它的方式.
快乐的编码,
Avrohom
| 归档时间: |
|
| 查看次数: |
6680 次 |
| 最近记录: |