gpt4 book ai didi

c# - Xamarin ContentView/View 生命周期

转载 作者:太空狗 更新时间:2023-10-29 23:36:15 25 4
gpt4 key购买 nike

版本

Xamarin.Android 8.2

Xamarin.Forms 2.5

小问题

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

长问题

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

示例

Sample

用法

<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 得到通知有什么好主意吗?

相关文章

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-own-lifecycle

谢谢!

最佳答案

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

基本上,扩展背后的原理是沿着 UI 树向上追踪父级。但是,当启动 ContentView(即调用 ctor)时,它可能尚未附加到父级,或者其父级(如果有)未附加到页面。这就是为什么我监听其 Parent 暂时为 null 的 Element 的 PropertyChanged 事件。附加元素后,搜索过程将继续。请注意,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();
}

好吧,我不确定这个肮脏的 hack 是否会导致一些副作用。希望最终正式版能有全生命周期支持的ContentView。

关于c# - Xamarin ContentView/View 生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49396160/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com