使用自定义渲染器

时间:2017-05-14 18:39:18

标签: c# android xamarin memory-leaks xamarin.forms

我在Xamarin.Forms / Android中使用MasterDetailPage,汉堡包页面中的每个项目代表一个页面。我通过调用:

来更改详细信息页面
Detail = new NavigationPage(new Pages.HomePage());
IsPresented = false;

我注意到这个页面的分配有点大(它的请求类似于22mb)。不仅如此,如果我反复按侧边栏的主页按钮,我会在大约5次点击后得到一个OutOfMemoryException。所以有些东西没有点击垃圾收集。

主页有一个自定义渲染器,它基本上使用三个png文件合成图像。这可以在我的手机上实现最小的减速,但是当它在屏幕上时,模拟器会显着滞后,这让我相信它会导致性能问题。

public class GoalJarViewRenderer : ImageRenderer
{

    Bitmap fillBmp = null;
    Bitmap jarHud = null;
    Paint font;
    Paint fontBold;
    string goalString = "";
    string progString = "";

    protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
    {
        this.SetWillNotDraw(false);
        base.OnElementChanged(e);

        Element.PropertyChanged += SignalUpdate;

        //Cache       
        if (fillBmp == null) fillBmp = BitmapFactory.DecodeResource(this.Context.Resources, Resource.Drawable.jar_fill);
        if (jarHud == null) jarHud = BitmapFactory.DecodeResource(this.Context.Resources, Resource.Drawable.jar_hud);
        if (font == null)
        {
            font = new Paint();
            font.AntiAlias = true;
            font.Color = Android.Graphics.Color.White;
            font.TextSize = 50;
            font.TextAlign = Paint.Align.Center;
        }
        if (fontBold == null)
        {
            fontBold = new Paint(font);
            fontBold.FakeBoldText = true;
            fontBold.TextSize = 80;
        }
    }


    private void SignalUpdate(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        GoalJarView handle = (GoalJarView)this.Element;
        goalString = String.Format("${0:#0.0#} / ${1:##.##}", handle.CurrentValue, handle.GoalValue);
        progString = String.Format("{0:##0.00}%", (handle.CurrentValue / handle.GoalValue) * 100);
        this.Invalidate();
    }

    public override void Draw(Canvas canvas)
    {
        base.Draw(canvas);

        //Draw the fill
        double LID_FIX = 0.91;
        GoalJarView handle = (GoalJarView)this.Element;
        double fillRatio = Math.Min(1,((handle.CurrentValue * LID_FIX) / handle.GoalValue));
        int srcStartY = (int)(fillBmp.Height - Math.Floor(fillBmp.Height * fillRatio));
        int destStartY = (int)(canvas.Height - Math.Floor(canvas.Height * fillRatio));
        Rect fillSrc = new Rect(0, srcStartY, fillBmp.Width, fillBmp.Height);
        RectF fillDest = new RectF(0, destStartY, canvas.Width, canvas.Height);
        canvas.DrawBitmap(fillBmp, fillSrc, fillDest, null);

        //Draw the text container
        canvas.DrawBitmap(jarHud, null, new Rect(0,0,canvas.Width,canvas.Height), null);

        //Draw the Text
        canvas.DrawText(progString, canvas.Width / 2, (canvas.Height / 2) - 20, fontBold);
        canvas.DrawText(goalString, canvas.Width / 2, (canvas.Height / 2) + 30, font);

    }
}

我被告知BitmapFactory.DecodeResource令人难以置信的负担,所以我把它移到了OnElementChanged而不是draw函数。我没有看到任何其他东西立即在Draw()内部征税,但我是Xamarin / Android的新手,并认为这个问题对于经验丰富的开发人员来说是显而易见的。

我已经尝试在MasterDetailPage上创建存储页面的局部变量,因此每次按下一个项目时都不需要创建局部变量,但这会在页面重新打开时导致崩溃,因为存储数据的实际控件类绑定为空。

导致此内存泄漏的原因是什么?如何更正?

0 个答案:

没有答案
相关问题