Xamarin ContentView/View生命周期 [英] Xamarin ContentView/View Lifecycle

查看:224
本文介绍了Xamarin ContentView/View生命周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Xamarin.Android 8.2

Xamarin.Android 8.2

Xamarin.Forms 2.5

Xamarin.Forms 2.5

我应该如何让ContentView知道其包含页面的生命周期状态(例如,出现,消失,正在休眠)

How do I, or should I let a ContentView know the life cycle state of its containing Page (e.g. Appearing, Disappearing, Sleeping)

我正在学习如何创建可重用的Xamarin ContentView.我决定创建一个控件<LabelCarousel/>,它将一个接一个地显示其子标签. 问题是我不知道如何停止切换内容的后台计时器

I am learning how to create a reusable Xamarin ContentView. I decide to create a control <LabelCarousel/> that will display its children label one after another. The problem is I have no idea how to stop the background timer that switches the content

<local:LabelCarousel>
    <Label>Hello</Label>
    <Label>Hola</Label>
</local:LabelCarousel>

实施

namespace XamarinStart.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    [ContentProperty("LabelContainer")]
    public partial class LabelCarousel : ContentView
    {
        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
        [Description("Labels"), Category("Data")]
        public List<Element> LabelContainer { get; } = new List<Element>();

        private int _index = 0;
        private Timer _timer = new Timer(2000);

        public LabelCarousel ()
        {
            InitializeComponent ();

            _timer.Elapsed += TimerEvent;
            _timer.Start();
            
        }

        private void TimerEvent(object sender, ElapsedEventArgs e)
        {
            if (_index >= LabelContainer.Count)
            {
                _index = 0;
            }

            var selected = LabelContainer[_index++];
            ChangeLabel((Label)selected);
        }

        private void ChangeLabel(Label lbl)
        {
            Device.BeginInvokeOnMainThread(async () =>
            {
                await this.FadeTo(0);
                Content = lbl;
                await this.FadeTo(1);
            });
        }
    }
}

问题

当我将此应用程序置于后台,或在该应用程序的顶部进行其他活动时,计时器仍在运行,浪费了CPU资源.有什么好主意让父页面更改状态时通知可重用的ContentView?

Problem

When I put this app into background, or push another activity on the top of this one, the timer is still running, wasting the CPU resource. Is there any good idea to let the reusable ContentView notified when the parent page changes the state?

https://forums.xamarin.com/discussion/38989/contentview-lifecycle 谢谢!

推荐答案

我自己发现了一种可能性,方法是使用类扩展将AttachLifecycleToPage方法添加到所有Element对象.

I figured out one possibility myself by using the class extension to add AttachLifecycleToPage method to all Element object.

基本上,扩展程序的原理是沿UI树跟踪父级.但是,启动ContentView时(即调用ctor),它可能尚未附加到父级,或者它的父级(如果有)未附加到页面.这就是为什么我要监听其Parent临时为null的Element的PropertyChanged事件.附加元素后,搜索过程将继续. 请注意,AttachLifecycleToPage不应在Element ctor中同步,这将导致死锁.

Basically, the principle behind the extension is tracing up the Parent along the UI tree. However, when the ContentView is initiated (i.e., ctor is called), it may not be attached to a parent yet, or its parent (if any) is not attached to a page. That's why I listen to the PropertyChanged event of the Element whose Parent is temporarily null. Once the Element gets attached, the searching process continues. Note that the AttachLifecycleToPage should not be synchronous in the Element ctor, which will causes a dead lock.

namespace XamarinStart.Extensions
{
    public static class PageAwareExtension
    {
        public static void AttachLifecycleToPage(this Element element, EventHandler onAppearing = null,
            EventHandler onDisappearing = null)
        {
            var task = new Task(() =>
            {
                var page = GetPage(element);
                if (page == null)
                {
                    return;
                }

                if (onAppearing != null)
                {
                    page.Appearing += onAppearing;
                }

                if (onDisappearing != null)
                {
                    page.Disappearing += onDisappearing;
                }
            });
            task.Start();
            return;
        }
        public static Page GetPage(this Element element, int timeout = -1)
        {
            if (element is Page) return (Page)element;

            Element el = element;
            // go up along the UI tree
            do
            {
                if (el.Parent == null)
                {
                    // either not attached to any parent, or no intend to attach to any page (is that possible?)
                    var signal = new AutoResetEvent(false);
                    PropertyChangedEventHandler handler = (object sender, PropertyChangedEventArgs args) =>
                    {
                        // https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Core/Element.cs
                        // Setting Parent property is tracked
                        Element senderElement = (Element) sender;
                        if (args.PropertyName == "Parent" && senderElement.Parent != null)
                        {
                            signal.Set();
                        }
                    };
                    el.PropertyChanged += handler;

                    var gotSignal = signal.WaitOne(timeout);
                    if (!gotSignal)
                    {
                        throw new TimeoutException("Cannot find the parent of the element");
                    }

                    el.PropertyChanged -= handler;
                } // if parent is null

                el = el.Parent;

            } while (! (el is Page));

            return (Page) el;
        }
    }
}

修改后的标签轮播

    public LabelCarousel ()
    {
        InitializeComponent ();

        _timer.Elapsed += TimerEvent;
        _timer.Start();

        this.AttachLifecycleToPage(OnAppearing, OnDisappearing); 
    }
    private void OnDisappearing(object sender, EventArgs eventArgs)
    {
        _timer.Stop();
    }

    private void OnAppearing(object sender, EventArgs eventArgs)
    {
        _timer.Start();
    }

好吧,我不确定这种肮脏的hack是否会引起一些副作用.我希望最终正式版本将具有具有完整生命周期支持的ContentView.

Well, I am not sure if this dirty hack can cause some side effect. I hope that eventually the official release will have the ContentView with full life cycle support.

这篇关于Xamarin ContentView/View生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆