ios 为什么我的collectionview是缓慢的滚动时向下或向上?如何修复性能问题?我已经清理了我的UI代码

gz5pxeao  于 2023-03-05  发布在  iOS
关注(0)|答案(2)|浏览(114)

为什么我的收藏视图是缓慢的滚动时,向下或向上?如何解决性能问题?
我看了所有关于这个的帖子,他们主要说要清理你的UI代码。如果UI代码很复杂,它会运行得很慢。这是有道理的。
但是在这里我已经清理了我的代码。在这里我能做的不多。
在collectionview中我有一个标签和图像。我在数据库中存储标签和图像路径。图像存储在appdatedirectory中
我认为是某个原因导致了性能问题,但我不确定是什么原因?

<ContentPage.Content>
        <StackLayout Padding="15" HorizontalOptions="CenterAndExpand">
            <!-- CollectionView -->
            <CollectionView ItemsSource="{Binding MyList}"
                                SelectionMode="Single"
                                SelectedItem="{Binding ItemSelectedEvent, Mode=TwoWay}"
                                SelectionChangedCommand="{Binding SelectionChangedCommand}"
                                ItemSizingStrategy="MeasureAllItems"
                                BackgroundColor="Transparent">
                <!-- Body -->
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                      <ContentView>
                              <grid>
                                <Frame CornerRadius="15" HasShadow="True" Padding="0" BackgroundColor="Black">
                                    <StackLayout>
                                        <StackLayout HorizontalOptions="FillAndExpand"
                                                     VerticalOptions="FillAndExpand">
                                            <Label Text="{Binding CardType}"
                                                        HorizontalTextAlignment="Center"
                                                       BackgroundColor="Black"
                                                       TextColor="white"></Label>
                                        </StackLayout>
                                        <!-- Image -->
                                        <StackLayout HorizontalOptions="FillAndExpand" 
                                                    VerticalOptions="FillAndExpand">
                                            <Image Source="{Binding CardFrontURL}"
                                                            Aspect="AspectFill"
                                                            HorizontalOptions="Fill"
                                                            VerticalOptions="Fill"></Image>
                                        </StackLayout>
                                    </StackLayout>
                                </Frame>
                    
                     </grid>
                 </ContentView>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
                <!-- Header -->
                <CollectionView.Header>
                    <StackLayout Orientation="Horizontal" HorizontalOptions="Center">
                        <Label Text="Cards List"  TextColor="Black" VerticalOptions="Center" FontSize="14" FontAttributes="Bold" />
                    </StackLayout>
                </CollectionView.Header>
            </CollectionView>
        </StackLayout>

    </ContentPage.Content>

在列表中存储标签和图像

public ObservableRangeCollection<MyModel> MyList{ get; set; }
a64a0gku

a64a0gku1#

第一步是找出是Image s还是您的DataTemplate导致了速度减慢。
测试:删除图像-注解掉<Image Source ...>
它运行得快得多吗?然后阅读关于获取和“缓存”图像的内容,这样它们就可以快速渲染。
如果不是图像,那么就是ItemTemplate的结构。
对于每一项,您创建一个ContentView、一个Grid和三个StackLayout,即每一项创建五个Layout类。
几乎没有必要像你在原始代码中那样嵌套垂直的StackLayout。你认为你为什么需要这些呢?为什么你不简单地有一个StackLayout,然后把LabelImage都放进去呢?
同样,为什么要使用Grid?它为您做了什么?

“干净的UI”在每个项目中使用尽可能少的Layout类。

我相信你可以把这五个减少到一个Layout

<CollectionView.ItemTemplate>
  <DataTemplate>
    <Frame Padding="0,0,0,10" ...>
        <StackLayout>
            <Label Text="{Binding CardType}" .../>
            <Image HeightRequest="200" Source="{Binding CardFrontURL}" .../>
        </StackLayout>
    </Frame>
  </DataTemplate>
</CollectionView.ItemTemplate>

在某些项目上,您可能需要PaddingMargin,以给予StackLayout所提供的垂直间距。
AFAIK,总是可以获得所需的间距而无需添加另一个Layout类。
最坏的情况是,您将一个BoxView与一个HeightRequest和一个BackgroundColor="Transparent"相加。
注:<Image HeightRequest="200" ...-如果固定高度适合您的需要,这允许布局逻辑在阅读图像源之前确定项目高度,这有助于使滚动平滑。如果没有这一点,当您第一次滚动列表时,可能会有一个或多个“打嗝”(“结巴”,短暂的停顿),而所需的图像被提取。
或者使用Grid,以便将来更灵活:

<CollectionView.ItemTemplate>
  <DataTemplate>
    <Frame Padding="0,0,0,10" ...>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            
            <Label Grid.Row="0" Text="{Binding CardType}" .../>
            <Image Grid.Row="1" Source="{Binding CardFrontURL}" .../>
        </Grid>
    </Frame>
  </DataTemplate>
</CollectionView.ItemTemplate>

Grid非常棒,因为您可以通过添加行和列来表示相当精细的布局,并且仍然只有一个布局类。

nhn9ugyo

nhn9ugyo2#

我得到了异步加载项的解决方案,在构造函数中添加一个元素,然后在任务中添加其他元素。
例如:

internal void SetData(CheckListData listData)
{
    _listData = listData;
    BindingContext = _listData;

   _items= new ObservableCollection<CheckBoxItem>(_listData.Items.Take(1));
    collectionView.ItemsSource = _items;
    loadData();
}

private void loadData()
{
    Task.Run(() =>
    {
        Thread.Sleep(50);
        foreach (var item in _listData.Items.Skip(1))
            _items.Add(item);
    });
}

相关问题