在处理大量数据时,延迟加载机制是必不可少的。本文将介绍如何轻松构建一个延迟加载的列表视图。以构建一个返回艺术家专辑列表的 Last.fm 应用为例,将逐步展开说明。
首先,创建一个新的Xamarin应用,并安装以下 NuGet 包:
接下来,将创建视图模型。
public class MainPageViewModel
{
private LastfmClient _client;
public MainPageViewModel()
{
_client = new LastfmClient("b471c30029ba983849723e5120e7504c", "24c4739698eebb92f792b118095dbdff");
Artists = GetArtists().ToStandardIncrementalLoadingCollection(10);
}
public IIncrementalLoadingCollection Artists { get; }
private IAsyncEnumerable GetArtists()
{
return AsyncEnumerableBuilder.FromPaged((i, i1) =>
_client.Artist.GetTopTracksAsync("Britney Spears", true, i, i1),
tracks => tracks.Select(t => new AlbumModel()
{
Name = t.Name,
Id = t.Id,
Image = t.Images.Large.ToString(),
Duration = t.Duration
}),
(i, tracks) => tracks.TotalItems > i,
(tracks, i) => tracks.Count() + i,
tracks =>
{
var pagenumber = (tracks?.Page ?? 0) + 1;
return pagenumber;
},
tracks => 20);
}
}
在这段代码中,创建了一个名为 MainPageViewModel
的视图模型类。初始化了 LastfmClient
并调用了 GetArtists
方法,该方法返回一个异步的可分页枚举集合。
为了实现延迟加载,使用了 AsyncEnumerableBuilder.FromPaged
方法,该方法允许从返回分页结果的方法中构建一个 IAsyncEnumerable
。然后,使用 ToStandardIncrementalLoadingCollection
方法将 IAsyncEnumerable
转换为可绑定的增量集合,该集合实现了 IIncrementalLoadingCollection
接口。
public interface IIncrementalLoadingCollection : ICollection, IEnumerable, IEnumerable
{
ICommand LoadMoreCommand { get; }
bool IsBusy { get; }
}
这个接口定义了两个属性:LoadMoreCommand
和 IsBusy
。LoadMoreCommand
用于加载更多数据,而 IsBusy
用于指示当前是否正在加载数据。
最后,构建视图。
<StackLayout BindingContext="{Binding Path=Artists}">
<xForms:SfListView x:Name="listView" ItemSpacing="10" LoadMoreOption="Manual" LoadMoreCommand="{Binding LoadMoreCommand}" IsBusy="{Binding IsBusy}" ItemsSource="{Binding }">
<xForms:SfListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Spacing="10">
<Image Source="{Binding Image}" HeightRequest="100" WidthRequest="100"/>
<Label Text="{Binding Name}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</xForms:SfListView.ItemTemplate>
<xForms:SfListView.LoadMoreTemplate>
<DataTemplate>
<Grid>
<Label Text="Load More Items" TextColor="Black" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" IsVisible="{Binding IsBusy, Converter={StaticResource inverseBoolConverter}, Source={x:Reference Name=listView}}"/>
<xForms:LoadMoreIndicator IsRunning="{Binding IsBusy, Source={x:Reference Name=listView}}" IsVisible="{Binding IsBusy, Source={x:Reference Name=listView}}" Color="Red" VerticalOptions="Center"/>
</Grid>
</DataTemplate>
</xForms:SfListView.LoadMoreTemplate>
</xForms:SfListView>
</StackLayout>