[Xamarin.Forms] CachingStrategy에서 ListView 가속화

18818 단어 XamarinXamarin.Forms
이 기사는 [초보자·학생씨 환영! ] Xamarin Part 1 Advent Calendar 2017의 23 일째 기사입니다.

가속화 방법



이 기사에서는 ListView의 Caching Strategy를 지정하여 ListView를 가속화합니다. 자세한 내용은 여기를 참조하십시오. htps : //에서 ゔぇぺぺr. 마린. 코 m/구이데 s/ぁ마린-후 rms/우세 r-이니 r 훗세/ぃstゔぃ에 w/페 r후 r 만세/

ViewCell(MyCell)



텍스트 1개와 이미지 4개로 구성된 ViewCell입니다. 큰 3장의 화상은 항상 같은 화상의 순서로 묘화해, 좌상단의 작은 화상은 3장의 화상으로부터 랜덤으로 선택한 것을 묘화 하고 있습니다. (이미지는 FLAT ICON DESIGN에서 빌렸습니다)



XAML



MyCell.xaml
<ViewCell 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="ViewCellTest.MyCell">
    <ViewCell.View>
        <StackLayout Orientation="Horizontal">
            <Image
                x:Name="iconImage"
                VerticalOptions="StartAndExpand"
                WidthRequest="50"
                HeightRequest="50"/>
            <StackLayout Orientation="Vertical">
                <Label
                    x:Name="titleLabel"
                    FontSize="Large"/>
                <StackLayout Orientation="Horizontal">
                    <!-- 大きな3つの画像はここでSourceを指定 -->
                    <Image
                        WidthRequest="100"
                        HeightRequest="100"
                        Source="image1.png"/>
                    <Image
                        WidthRequest="100"
                        HeightRequest="100"
                        Source="image2.png"/>
                    <Image
                        WidthRequest="100"
                        HeightRequest="100"
                        Source="image3.png"/>
                </StackLayout>
            </StackLayout>
        </StackLayout>
    </ViewCell.View>
</ViewCell>

코드 비하인드



MyCell.xaml.cs
public partial class MyCell : ViewCell
{
    public static readonly BindableProperty IconImageSourceProperty = BindableProperty.Create(
        nameof(IconImageSource),
        typeof(ImageSource),
        typeof(MyCell),
        propertyChanged: (b, o, n) => (b as MyCell).iconImage.Source = n as ImageSource);

    public static readonly BindableProperty TitleProperty = BindableProperty.Create(
        nameof(Title),
        typeof(string),
        typeof(MyCell),
        propertyChanged: (b, o, n) => (b as MyCell).SetTitle(n as string));

    public ImageSource IconImageSource
    {
        get { return (ImageSource)GetValue(IconImageSourceProperty); }
        set { SetValue(IconImageSourceProperty, value); }
    }

    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    // このようにメソッドからテキストをセットしてもOK
    private void SetTitle(string title)
    {
        titleLabel.Text = title;
    }

    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();
        // BindablePropertyのpropertyChangedを使わないなら、ここでコントロールの設定をする
    }

    public MyCell()
    {
        InitializeComponent();
        Console.WriteLine("MyCellが生成されました");
    }
}

BindableProperty의 propertyChanged 또는 오버라이드(override) 한 OnBindingContextChanged() 의 어느쪽이든으로, XAML로 정의한 컨트롤의 property를 설정해 봅시다.

ListView를 표시하는 페이지 (MainPage)



MyCell을 사용하여 ListView를 표시하는 MainPage를 만듭니다. 코드 비하인드는 InitializeComponent() 이외 아무것도 쓰지 않으므로 생략합니다.

MyCell에 사용할 데이터 클래스



CellItem.cs
public class CellItem
{
    public ImageSource IconImageSource { get; set; }
    public string Title { get; set; }

    public CellItem(string iconImageName, string title)
    {
        IconImageSource = ImageSource.FromFile(iconImageName);
        Title = title;
    }
}

XAML



ItemsSource는 MainViewModel의 Items에 바인딩됩니다.

MainPage.xaml
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:ViewCellTest"
    x:Class="ViewCellTest.MainPage">

    <ContentPage.BindingContext>
        <local:MainViewModel/>
    </ContentPage.BindingContext>

    <ListView
        ItemsSource="{Binding Items}"
        HasUnevenRows="True">
        <ListView.ItemTemplate>
            <DataTemplate>
                <local:MyCell
                    IconImageSource="{Binding IconImageSource}"
                    Title="{Binding Title}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

ViewModel



데이터의 생성을 생성자로 하고 있을 뿐입니다.

MainViewModel.cs
public class MainViewModel
{
    public ObservableCollection<CellItem> Items { get; set; }

    public MainViewModel()
    {
        var random = new Random();
        // データ生成。画像はimage1.png, image2.png, image3.pngの三枚を用意した 
        var data = Enumerable.Range(1, 100)
            .Select(x => new CellItem($"image{random.Next(1, 4)}.png", $"MyCell{x}"));
        Items = new ObservableCollection<CellItem>(data);
    }
}

실행 결과





프로그램이 완성되었기 때문에 기동해 보면 이런 느낌이 됩니다.
스크롤에 화상의 로드가 따라잡지 않네요. 그럼 이것을 가속화하겠습니다.

RecycleElement 지정



MainPage.xaml
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:ViewCellTest"
    x:Class="ViewCellTest.MainPage">

    <ContentPage.BindingContext>
        <local:MainViewModel/>
    </ContentPage.BindingContext>

    <ListView
        ItemsSource="{Binding Items}"
        HasUnevenRows="True"
        CachingStrategy="RecycleElement"> <!-- 新しく追加 -->
        <ListView.ItemTemplate>
            <DataTemplate>
                <local:MyCell
                    IconImageSource="{Binding IconImageSource}"
                    Title="{Binding Title}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

ListView 에 CachingStrategy="RecycleElement" (디폴트는 RetainElement)를 지정해 주는 것 뿐입니다. 이렇게 하면 생성된 MyCell 클래스의 인스턴스를 사용하면서 BindingContext를 전환해주므로 MyCell 생성에 드는 비용을 줄일 수 있고 로드가 빨라집니다.



MyCell 의 생성자 에 쓴 Console.WriteLine("MyCellが生成されました"); 보다 , 최초의 MyCell 의 생성 후에는 , 인스턴스가 사용회전되고 있는 것을 확인할 수 있습니다.

결론



나란히 비교해 보면 이만큼 차이가 있습니다.


RetainElement(기본값)
RecycleElement






이번 작성한 MyCell에서는 CachingStrategy에 RecycleElement를 지정하는 것으로 고속화를 할 수 있었습니다만, 어떠한 Cell에서도 RecycleElement로 고속화할 수 있는 것은 아닙니다. 데이터 바인딩의 수가 20 이상 등의 경우에는, 디폴트의 RetainElement 가 좋을 것 같습니다. 작성한 셀에 맞게 CachingStrategy를 적절하게 설정해야 합니다.

좋은 웹페이지 즐겨찾기