简体   繁体   English

如何提高标签页中的加载性能 xamarin forms

[英]How to improve loading performance in Tabbed Page xamarin forms

I am trying to create bottom tabbed page in Xamarin forms and i am doing this for Android.我正在尝试在 Xamarin forms 中创建底部标签页,我正在为 Android 执行此操作。

here i am using latest version of Xamarin Forms.这里我使用的是最新版本的 Xamarin Forms。

My sample Bottom tabbed page like below.我的示例底部标签页如下所示。

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:views="clr-namespace:SampleTabbedPage.Views"
            xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
            android:TabbedPage.ToolbarPlacement="Bottom"
            android:TabbedPage.BarItemColor="Gray"
            android:TabbedPage.BarSelectedItemColor="Blue"
             mc:Ignorable="d"
             x:Class="SampleTabbedPage.Views.SampleTabbed">
  <!--Pages can be added as references or inline-->

    <NavigationPage
        Title="Main"
        NavigationPage.HasNavigationBar="False">
        <x:Arguments>
            <views:SampleDetailsPage/>
        </x:Arguments>
    </NavigationPage>

    <ContentPage Title="Tab 1" />
  <ContentPage Title="Tab 2" />
</TabbedPage>

My sample details page like我的示例详细信息页面如

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="SampleTabbedPage.Views.SampleDetailsPage"
             BackgroundColor="Gray">
    <ContentPage.Content>
        <StackLayout>
            <ListView BackgroundColor="White" ItemTapped="ListView_ItemTapped">
                <ListView.ItemsSource>
                    <x:Array Type="{x:Type x:String}">
                        <x:String>Mango</x:String>
                        <x:String>Banana</x:String>
                        <x:String>Pinaple</x:String>
                        <x:String>Apple</x:String>
                        <x:String>Avacado</x:String>
                        <x:String>Coconut</x:String>
                        <x:String>Dragan Fruit</x:String>
                        <x:String>Pomaganate</x:String>
                        <x:String>Wood Apple</x:String>
                    </x:Array>
                </ListView.ItemsSource>
            </ListView>

        </StackLayout>
    </ContentPage.Content>
</ContentPage>

And the navigation i am doing as follows我正在做的导航如下

in App.xamal.cs在 App.xamal.cs 中

MainPage = new NavigationPage(new FirstPage());

I have simple first page我有简单的第一页

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="SampleTabbedPage.Views.FirstPage">
    <ContentPage.Content>
        <StackLayout>
            <Button Text="Click Me!" Clicked="Button_Clicked"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

here in button click event i do the navigation to " Sample Tabbed Page "在按钮单击事件中,我导航到“示例标签页

await Navigation.PushAsync(new SampleTabbed());

This is working fine.这工作正常。 but there is a performance issue.但存在性能问题。

if i run this and click on button in First page it is taking 3 seconds to load tabbed page.如果我运行此程序并单击第一页中的按钮,则加载选项卡式页面需要3 秒钟

if i remove list view in sample detail page it take 2 seconds to load.如果我删除示例详细信息页面中的列表视图,则需要2 秒才能加载。

but if i add just a content page to click event it take only milliseconds to load.但是如果我只添加一个内容页面来单击事件,则只需几毫秒即可加载。

Am i doing some thing wrong with implementing tabbed page?我在实现选项卡式页面时做错了什么?

or或者

is there any way to improve the loading performance with tabbed pages.有什么方法可以提高标签页的加载性能。

A solution is to make the heavy pages load their content in a lazy manner, only when their tab becomes selected.一种解决方案是让重页以惰性方式加载其内容,仅当它们的选项卡被选中时。 This way, since these pages are now empty when TabbedPage is created, navigating to the TabbedPage suddenly becomes very fast!这样,由于在创建 TabbedPage 时这些页面现在是空的,因此导航到 TabbedPage 突然变得非常快!

1.create a behavior for the TabbedPage page, called ActivePageTabbedPageBehavior . 1.为 TabbedPage 页面创建一个行为,称为ActivePageTabbedPageBehavior

class ActivePageTabbedPageBehavior : Behavior<TabbedPage>
{
 protected override void OnAttachedTo(TabbedPage tabbedPage)
  {
    base.OnAttachedTo(tabbedPage);
    tabbedPage.CurrentPageChanged += OnTabbedPageCurrentPageChanged;
  }

 protected override void OnDetachingFrom(TabbedPage tabbedPage)
  {
    base.OnDetachingFrom(tabbedPage);
    tabbedPage.CurrentPageChanged -= OnTabbedPageCurrentPageChanged;
  }

 private void OnTabbedPageCurrentPageChanged(object sender, EventArgs e)
  {
    var tabbedPage = (TabbedPage)sender;

    // Deactivate previously selected page
    IActiveAware prevActiveAwarePage = tabbedPage.Children.OfType<IActiveAware>()
        .FirstOrDefault(c => c.IsActive && tabbedPage.CurrentPage != c);
    if (prevActiveAwarePage != null)
    {
        prevActiveAwarePage.IsActive = false;
    }

    // Activate selected page
    if (tabbedPage.CurrentPage is IActiveAware activeAwarePage)
    {
        activeAwarePage.IsActive = true;
    }
  }
}

2.define IActiveAware interface 2.定义IActiveAware接口

interface IActiveAware
  {
    bool IsActive { get; set; }
    event EventHandler IsActiveChanged;
  }

3.create a base generic abstract class called LoadContentOnActivateBehavior 3.创建一个名为LoadContentOnActivateBehavior的基本通用抽象 class

abstract class LoadContentOnActivateBehavior<TActivateAwareElement> : Behavior<TActivateAwareElement>
   where TActivateAwareElement : VisualElement
 {
  public DataTemplate ContentTemplate { get; set; }

  protected override void OnAttachedTo(TActivateAwareElement element)
   {
     base.OnAttachedTo(element);
     (element as IActiveAware).IsActiveChanged += OnIsActiveChanged;
   }

  protected override void OnDetachingFrom(TActivateAwareElement element)
   {
     (element as IActiveAware).IsActiveChanged -= OnIsActiveChanged;
     base.OnDetachingFrom(element);
   }

  void OnIsActiveChanged(object sender, EventArgs e)
   {
     var element = (TActivateAwareElement)sender;
     element.Behaviors.Remove(this);
     SetContent(element, (View)ContentTemplate.CreateContent());
   }

  protected abstract void SetContent(TActivateAwareElement element, View contentView);
}

4.the specialized LazyContentPageBehavior 4.专门的LazyContentPageBehavior

class LazyContentPageBehavior : LoadContentOnActivateBehavior<ContentView>
 {
   protected override void SetContent(ContentView element, View contentView)
    {
      element.Content = contentView;
    }
 }

then we can use in xaml like this:然后我们可以像这样在 xaml 中使用:

<TabbedPage>
  <TabbedPage.Behaviors>
    <local:ActivePageTabbedPageBehavior />
  </TabbedPage.Behaviors>

<ContentPage Title="First tab">
    <Label Text="First tab layout" />
</ContentPage>

<local:LazyLoadedContentPage Title="Second tab">
    <ContentPage.Behaviors>
        <local:LazyContentPageBehavior ContentTemplate="{StaticResource ContentTemplate}" />
    </ContentPage.Behaviors>
    <ContentPage.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="ContentTemplate">
                <!-- Complex and slow to render layout -->
                <local:SlowContentView />
            </DataTemplate>
        </ResourceDictionary>
    </ContentPage.Resources>
</local:LazyLoadedContentPage>
</TabbedPage>

we moved the ContentPage complex layout to become a DataTemplate.我们将 ContentPage 复杂布局移动为 DataTemplate。

Here's the custom LazyLoadedContentPage page which is activation aware:这是激活感知的自定义LazyLoadedContentPage页面:

class LazyLoadedContentPage : ContentPage, IActiveAware
{
  public event EventHandler IsActiveChanged;

  bool _isActive;
  public bool IsActive
   {
     get => _isActive;
     set
      {
        if (_isActive != value)
        {
            _isActive = value;
            IsActiveChanged?.Invoke(this, EventArgs.Empty);
        }
      }
   }
 }

SlowContentView do some complex things SlowContentView做一些复杂的事情

 public partial class SlowContentView : ContentView
{
    public SlowContentView()
    {
        InitializeComponent();

        // Simulating a complex view
        ...
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM