Share via


ListView 성능

모바일 애플리케이션을 작성할 때 성능이 중요합니다. 사용자는 부드러운 스크롤 및 빠른 로드 시간을 기대하게되었습니다. 사용자의 기대치를 충족하지 못하면 애플리케이션 저장소 또는 기간 업무 애플리케이션의 경우 조직의 시간과 비용이 발생합니다.

데이터를 Xamarin.FormsListView 표시하기 위한 강력한 보기이지만 몇 가지 제한 사항이 있습니다. 사용자 지정 셀을 사용할 때 스크롤 성능이 저하될 수 있습니다. 특히 중첩된 뷰 계층 구조가 깊거나 복잡한 측정이 필요한 특정 레이아웃을 사용하는 경우 더욱 그렇습니다. 다행히 성능 저하를 방지하는 데 사용할 수 있는 기술이 있습니다.

캐싱 전략

ListView는 화면에 맞는 것보다 훨씬 더 많은 데이터를 표시하는 데 자주 사용됩니다. 예를 들어 음악 앱에는 수천 개의 항목이 있는 노래 라이브러리가 있을 수 있습니다. 모든 항목에 대한 항목을 만들면 귀중한 메모리가 낭비되고 성능이 저조합니다. 행을 지속적으로 만들고 삭제하려면 애플리케이션에서 개체를 지속적으로 인스턴스화하고 클린 때문에 성능이 저조합니다.

메모리를 절약하기 위해 각 플랫폼에 해당하는 네이티브 ListView 에는 행을 재사용하기 위한 기본 제공 기능이 있습니다. 화면에 표시되는 셀만 메모리에 로드되고 콘텐츠기존 셀에 로드됩니다. 이 패턴은 애플리케이션이 수천 개의 개체를 인스턴스화하여 시간과 메모리를 절약하는 것을 방지합니다.

Xamarin.Forms 는 ListView 다음 값을 포함하는 열거형을 ListViewCachingStrategy 통해 셀을 다시 사용할 수 있도록 허용합니다.

public enum ListViewCachingStrategy
{
    RetainElement,   // the default value
    RecycleElement,
    RecycleElementAndDataTemplate
}

참고 항목

UWP(유니버설 Windows 플랫폼)는 항상 캐싱을 사용하여 성능을 향상시키기 때문에 캐싱 전략을 무시 RetainElement 합니다. 따라서 기본적으로 캐싱 전략이 적용되는 것처럼 RecycleElement 동작합니다.

RetainElement

RetainElement 캐싱 전략은 목록의 ListView 각 항목에 대한 셀을 생성하며 기본 ListView 동작임을 지정합니다. 다음과 같은 경우에 사용해야 합니다.

  • 각 셀에는 많은 수의 바인딩이 있습니다(20-30 이상).
  • 셀 서식 파일이 자주 변경됩니다.
  • 테스트 결과 캐싱 전략으로 RecycleElement 인해 실행 속도가 감소하는 것으로 나타났습니다.

사용자 지정 셀을 사용할 때 캐싱 전략의 RetainElement 결과를 인식하는 것이 중요합니다. 셀 초기화 코드는 각 셀 만들기에 대해 실행해야 하며, 초당 여러 번 실행될 수 있습니다. 이 경우 중첩된 StackLayout 여러 인스턴스를 사용하는 것과 같이 페이지에서 잘 작동하는 레이아웃 기술은 사용자가 스크롤할 때 실시간으로 설정 및 제거될 때 성능 병목 상태가 됩니다.

RecycleElement

RecycleElement 캐싱 전략은 목록 셀을 재활용하여 메모리 공간 및 실행 속도를 최소화하도록 지정 ListView 합니다. 이 모드가 항상 성능 향상을 제공하는 것은 아닙니다. 향상된 성능을 확인하기 위해 테스트를 수행해야 합니다. 그러나 선호하는 선택이며 다음과 같은 경우에 사용해야 합니다.

  • 각 셀에는 작은 수에서 보통 수의 바인딩이 있습니다.
  • 각 셀은 BindingContext 모든 셀 데이터를 정의합니다.
  • 각 셀은 크게 비슷하며 셀 템플릿이 흔들리지 않습니다.

가상화 중에 셀의 바인딩 컨텍스트가 업데이트되므로 애플리케이션이 이 모드를 사용하는 경우 바인딩 컨텍스트 업데이트가 적절하게 처리되도록 해야 합니다. 셀에 대한 모든 데이터는 바인딩 컨텍스트에서 제공해야 합니다. 그렇지 않은 경우 일관성 오류가 발생할 수 있습니다. 데이터 바인딩을 사용하여 셀 데이터를 표시하여 이 문제를 방지할 수 있습니다. 또는 다음 코드 예제와 OnBindingContextChanged 같이 사용자 지정 셀의 생성자가 아닌 재정의에서 셀 데이터를 설정해야 합니다.

public class CustomCell : ViewCell
{
    Image image = null;
    
    public CustomCell ()
    {
        image = new Image();
        View = image;
    }
    
    protected override void OnBindingContextChanged ()
    {
        base.OnBindingContextChanged ();
        
        var item = BindingContext as ImageItem;
        if (item != null) {
            image.Source = item.ImageUrl;
        }
    }
}

자세한 내용은 바인딩 컨텍스트 변경 내용을 참조 하세요.

iOS 및 Android에서 셀이 사용자 지정 렌더러를 사용하는 경우 속성 변경 알림이 올바르게 구현되었는지 확인해야 합니다. 셀을 다시 사용하면 바인딩 컨텍스트가 사용 가능한 셀의 값으로 PropertyChanged 업데이트될 때 해당 속성 값이 변경되고 이벤트가 발생합니다. 자세한 내용은 ViewCell 사용자 지정을 참조하세요.

DataTemplateSelector를 사용하는 RecycleElement

a를 ListViewDataTemplateSelector 사용하여 선택하는 DataTemplateRecycleElement 경우 캐싱 전략은 캐시DataTemplate되지 않습니다. 대신 DataTemplate 목록의 각 데이터 항목에 대해 a가 선택됩니다.

참고 항목

캐싱 전략에는 RecycleElement 2.4에서 Xamarin.Forms 도입된 필수 구성 요소가 있으며, a가 각각 DataTemplate 동일한 ViewCell 형식을 반환해야 하는 것을 선택 DataTemplate 하라는 메시지가 표시될 때 DataTemplateSelector 입니다. 예를 들어 ListViewDataTemplateSelector 반환할 수 있는(형식MyViewCellA을 반환 MyDataTemplateA 하는 경우MyDataTemplateA) 또는 MyDataTemplateB (형식을 MyViewCellB반환 ViewCellViewCell 하는 경우MyDataTemplateB) MyDataTemplateA 반환되는 경우 반환 MyViewCellA 해야 하거나 예외가 throw됩니다.

RecycleElementAndDataTemplate

RecycleElementAndDataTemplate 캐싱 전략은 캐싱 전략을 기반으로 RecycleElement 하며, 또한 캐싱을 사용하여 DataTemplateSelector 선택할 DataTemplateDataTemplateListView 목록의 항목 유형에 따라 캐시되도록 합니다. 따라서 DataTemplate항목 인스턴스당 한 번이 아니라 항목 유형별로 한 번 선택됩니다.

참고 항목

캐싱 전략에는 RecycleElementAndDataTemplate 반환되는 필수 구성 요소가 DataTemplate있어야 합니다 DataTemplateType.DataTemplateSelector

캐싱 전략 설정

ListViewCachingStrategy 다음 코드 예제와 ListView 같이 생성자 오버로드를 사용하여 열거형 값을 지정합니다.

var listView = new ListView(ListViewCachingStrategy.RecycleElement);

XAML에서 아래 XAML에 표시된 대로 특성을 설정합니다 CachingStrategy .

<ListView CachingStrategy="RecycleElement">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
              ...
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

이 메서드는 C#의 생성자에서 캐싱 전략 인수를 설정하는 것과 동일한 효과가 있습니다.

서브클래싱된 ListView에서 캐싱 전략 설정

CachingStrategy 서브클래스 ListView 된 XAML에서 특성을 설정해도 속성ListView이 없 CachingStrategy 으므로 원하는 동작이 생성되지 않습니다. 또한 XAMLC를 사용하는 경우 'CachingStrategy'에 대한 속성, 바인딩 가능한 속성 또는 이벤트를 찾을 수 없음 오류 메시지가 생성됩니다.

이 문제에 대한 해결 방법은 매개 변수를 수락 ListViewCachingStrategy 하고 기본 클래스에 전달하는 서브클래스에 ListView 생성자를 지정하는 것입니다.

public class CustomListView : ListView
{
    public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
    {
    }
    ...
}

ListViewCachingStrategy 그런 다음, 구문을 사용하여 x:Arguments XAML에서 열거형 값을 지정할 수 있습니다.

<local:CustomListView>
    <x:Arguments>
        <ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
    </x:Arguments>
</local:CustomListView>

ListView 성능 제안

의 성능을 향상시키기 위한 많은 기술이 있습니다 ListView. 다음 제안 사항으로 ListView의 성능이 향상될 수 있습니다.

  • 컬렉션은 ItemsSource 임의 IEnumerable<T> 액세스를 지원하지 않으므로 컬렉션 대신 컬렉션 IEnumerable<T> 에 속성을 IList<T> 바인딩합니다.
  • 가능할 때마다 대신 기본 제공 셀(예: TextCell / SwitchCell )을 ViewCell 사용합니다.
  • 더 적은 요소를 사용합니다. 예를 들어 여러 레이블 대신 단일 FormattedString 레이블을 사용하는 것이 좋습니다.
  • 서로 다른 형식의 ListViewTableView 데이터인 비종종 데이터를 표시할 때 해당 데이터를 대체합니다.
  • 메서드 사용을 제한합니다 Cell.ForceUpdateSize . 과도하게 사용하면 성능이 저하됩니다.
  • Android에서는 인스턴스화된 후 행 구분 기호 표시 유형 또는 색을 설정 ListView하지 마세요. 이로 인해 성능이 저하됩니다.
  • 에 따라 셀 레이아웃을 BindingContext변경하지 않습니다. 레이아웃을 변경하면 측정 및 초기화 비용이 크게 발생합니다.
  • 깊이 중첩된 레이아웃 계층 구조를 사용하지 않습니다. 사용 AbsoluteLayout 하거나 Grid 중첩을 줄이는 데 도움이 될 수 있습니다.
  • (컴퓨팅에 가장 저렴함)Fill 이외의 Fill 특정 LayoutOptions 을 사용하지 마세요.
  • 다음과 같은 이유로 내부에 ScrollView 배치 ListView 하지 마십시오.
    • 자체 ListView 스크롤을 구현합니다.
    • ListView 부모ScrollView에 의해 처리되므로 제스처는 수신되지 않습니다.
    • ListView 목록의 요소와 함께 스크롤되는 사용자 지정된 머리글 및 바닥글을 표시하여 사용된 기능을 ScrollView 제공할 수 있습니다. 자세한 내용은 머리글 및 바닥글을 참조 하세요.
  • 셀에 제시된 특정하고 복잡한 디자인이 필요한 경우 사용자 지정 렌더러를 고려합니다.

AbsoluteLayout 에는 단일 측정값 호출 없이 레이아웃을 수행할 가능성이 있으므로 성능이 높습니다. 사용할 수 없는 경우 AbsoluteLayout 다음을 고려합니다 RelativeLayout. 사용하는 RelativeLayout경우 제약 조건을 직접 전달하는 것이 식 API를 사용하는 것보다 훨씬 빠릅니다. 이 메서드는 식 API가 JIT를 사용하고 iOS에서 트리를 해석해야 하므로 속도가 느립니다. 식 API는 초기 레이아웃 및 회전에만 필요한 페이지 레이아웃에 적합하지만 ListView스크롤하는 동안 지속적으로 실행되는 경우 성능이 저하됩니다.

또는 해당 셀에 대한 ListView 사용자 지정 렌더러를 빌드하는 것은 스크롤 성능에 대한 레이아웃 계산의 영향을 줄이는 한 가지 방법입니다. 자세한 내용은 ListView 사용자 지정 및 ViewCell 사용자 지정을 참조하세요.