选项卡式页面,导致更多时间加载应用程序

时间:2019-06-04 02:37:28

标签: xaml xamarin.forms prism tabbedpage

我正在尝试开发具有选项卡式页面的xamarin应用。

我有3个主要标签。每个页面的viewmodel构造函数都有3-5个Api调用。因此,加载我的应用程序(用于打开)需要花费更多时间(20秒)。

mainpage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage  xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Myapplication.Views.MenuPage"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             xmlns:b="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True" 
              xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
             xmlns:views="clr-namespace:Dyocense.Views"
             android:TabbedPage.ToolbarPlacement="Bottom"
             android:TabbedPage.IsSwipePagingEnabled="False"
             >

        <views:A Title="A" Icon="dsjsdsd_18dp.png" ></views:A>
        <views:B Title="B" Icon="askjasa.png"></views:B>
        <views:C Title="C" Icon="abc.png"></views:C>
        <views:D Title="D" Icon="abc.png"></views:D>


</TabbedPage>

如何仅在应用程序加载时加载第一个选项卡(A)详细信息页面,而在更改选项卡时仅加载其余页面。

2 个答案:

答案 0 :(得分:1)

一种解决方案是使沉重的页面仅在其标签被选中时才以懒惰的方式加载其内容。这样,由于创建TabbedPage时这些页面现在为空,因此导航到TabbedPage突然变得非常快!

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。定义 IActiveAware 界面

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

3。创建一个称为 LoadContentOnActivateBehavior

的基本通用抽象类。
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。专门的 LazyContentPageBehavior

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

然后我们可以像这样在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>

我们将ContentPage复杂布局移动到了DataTemplate中。

这是自定义的 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 做一些复杂的事情

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

        // Simulating a complex view
        ...
    }
}

您可以参考link

答案 1 :(得分:0)

作为一种解决方法,我创建了一个扩展Xamarin.Forms.TabbedPage的新类,并且每次单击其中一个选项卡(或通常已显示)时都发送一条消息

public enum TabbedPages
{
    MyPage1 = 0,
    MyPage2 = 1,
    MyPage3 = 2,

}

public class BottomBarPage : Xamarin.Forms.TabbedPage
{

    protected override void OnCurrentPageChanged()
    {
        base.OnCurrentPageChanged();

        var newCurrentPage = (TabbedPages)Children.IndexOf(CurrentPage);

        MessagingCenter.Send<Xamarin.Forms.TabbedPage>(this, newCurrentPage.ToString("g"));

    }
}

,然后在单击选项卡上用于加载的每个页面的视图模型上,我订阅消息并调用我的API

public class MyPage2ViewModel
{
    public MyPage2ViewModel()
    {
        MessagingCenter.Subscribe<TabbedPage>(this, TabbedPages.MyPage2 .ToString("g"), async (obj) =>
        {
            //API call
        });
    }
}