为啥我的收藏视图在向下或向上滚动时很慢?如何解决性能问题?我已经清理了我的 UI 代码

Posted

技术标签:

【中文标题】为啥我的收藏视图在向下或向上滚动时很慢?如何解决性能问题?我已经清理了我的 UI 代码【英文标题】:Why my collectionview is slow when scrolling down or up? how to fix performance issue? I already Cleaned my UI Code为什么我的收藏视图在向下或向上滚动时很慢?如何解决性能问题?我已经清理了我的 UI 代码 【发布时间】:2021-08-17 03:55:01 【问题描述】:

为什么我的收藏视图在向下或向上滚动时很慢?如何解决性能问题?

我阅读了所有关于此的帖子,他们主要说要清理您的 UI 代码。如果 UI 代码复杂,它会运行缓慢。有道理。

但是在这里我已经清理了我的代码。我在这里无能为力。

在 collectionview 我有一个标签和图像。我将标签和图像路径存储在数据库中。图像存储在 appdata 目录中

我认为某些原因导致性能问题,但我不确定是什么原因?

    <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; 

【问题讨论】:

CardFrontURL 是 url 还是文件路径? CardFromURL 只是一个字符串。此字符串是手机上存储图像的 appdata 文件夹的路径 我看到您已编辑问题以删除 ContentViewGrid。现在,那些StackLayouts 呢? [请勿将它们从您的问题中编辑出来-这样做会使此问答对将来的任何人都无用-只需报告是否按照我的说明进行操作,以制作不需要太多它们的更简单的布局,从而显着加快滚动速度,或不是。] 如果布局结果不是原因,那么就说 - 我们会知道我的回答在这种情况下不相关。 【参考方案1】:

第一步是查明是Images 还是您的DataTemplate 导致了减速。

测试:删除图像 - 注释掉 &lt;Image Source ...&gt;

它运行得更快吗?然后阅读有关获取和“缓存”图像的信息,以便可以快速渲染它们。


如果不是图片,那就是你的ItemTemplate的结构。

为每个项目创建一个ContentView、一个Grid 和三个StackLayouts。每个项目有五个 Layout 类。

几乎不需要像在原始代码中那样嵌套所有垂直的StackLayouts。为什么你认为你需要这些?你为什么不简单地拥有一个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,以提供StackLayouts 提供的垂直间距。

AFAIK,无需添加另一个 Layout 类总是可以获得所需的间距。

最坏的情况是,您将BoxView 添加到HeightRequestBackgroundColor="Transparent"


注意:&lt;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 很棒,因为您可以通过添加行和列来表示相当精细的布局,并且仍然只有一个布局类。

【讨论】:

很好的提示,谢谢!!!我从中学到了很多。我做了所有这些改变。所以现在它的滚动很顺利。但是向下滚动,它现在只卡住了一次。这比以前顺畅多了! @StarGates - 甜!很高兴这有帮助。 @StarGates - 改善“卡住一次”的情况,可能需要预缓存图像。当您的页面首次加载时,您会启动一个后台线程,该线程开始获取图像 URL,并将这些图像存储在字典中。正确处理有点棘手,因为您有一个后台线程添加到字典中,而前台 (UI) 正在尝试从字典中读取。如果它还没有在字典中,您必须优先获取所需的优先级。未来的主题供您探索。 :) @StarGates - 如果您将HeightRequest="NN" 添加到Image,其中NN 表示您确定有用的某个特定值,例如“50”,那么布局逻辑可以在读取之前确定项目高度图片来源。这可能有助于解决一次性故障。 另外,将VerticalOptions 移至Fill 以使其流畅

以上是关于为啥我的收藏视图在向下或向上滚动时很慢?如何解决性能问题?我已经清理了我的 UI 代码的主要内容,如果未能解决你的问题,请参考以下文章

如何在快速向上或向下滚动时退出键盘? [关闭]

为啥我的导航栏在向下滚动时不隐藏而在向上滚动时出现?

使用向上/向下滑动动画显示和隐藏视图

向上或向下滚动列表视图的问题

UITableView,如何修复页脚,使其在滚动时永远不会向上或向下移动?

Flutter ListVİew 总是在向上或向下滚动时重新渲染