Xamarin ContentView /查看生命周期

Xamarin.Android 8.2

Xamarin.Forms 2.5

简短的问题

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

很长的问题

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

样品

样品

用法

     

履行

 namespace XamarinStart.Views { [XamlCompilation(XamlCompilationOptions.Compile)] [ContentProperty("LabelContainer")] public partial class LabelCarousel : ContentView { [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] [Description("Labels"), Category("Data")] public List LabelContainer { get; } = new List(); 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通知?

相关文章

https://forums.xamarin.com/discussion/38989/contentview-lifecycle https://forums.xamarin.com/discussion/65140/we-need-a-way-for-contentview-and-viewcells-to-monitor -their-自己的生命周期

谢谢!

我通过使用类扩展将AttachLifecycleToPage方法添加到所有Element对象,我自己想出了一种可能性。

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

扩展代码

 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; } } } 

修改过的LabelCarousel

  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(); } 

好吧,我不确定这个肮脏的黑客是否会引起一些副作用。 我希望最终正式版本能够为ContentView提供全生命周期支持。