You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

首次打开ContentPage时ListView图片未显示,如何预加载?

解决ListView首次加载不显示UriImageSource图片的预加载方案

这个问题我做项目时也碰到过——首次打开页面时图片还没完成异步下载,ListView绑定后没法自动感知图片加载状态,导致页面空白;第二次打开因为缓存存在,图片就能正常显示。下面给你几个原生的预加载解决方案,亲测有效:

方案1:绑定前提前异步加载所有图片

核心思路是在ViewModel中先完成所有图片的加载,确认加载完成后再把图片源集合赋值给ListView的ItemsSource,这样UI展示时图片已经在缓存里了。

代码示例(ViewModel中)

using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Forms;

public class YourViewModel : INotifyPropertyChanged
{
    public ObservableCollection<UriImageSource> Images { get; } = new ObservableCollection<UriImageSource>();

    // 传入你的图片URL列表
    public async Task LoadAndPrepareImagesAsync(List<string> imageUrls)
    {
        var imageSources = new List<UriImageSource>();
        var loadTasks = new List<Task>();

        foreach (var url in imageUrls)
        {
            var uriSource = new UriImageSource
            {
                Uri = new Uri(url),
                CachingEnabled = true,
                // 可选:设置超时时间,避免无限等待
                Timeout = TimeSpan.FromSeconds(10)
            };
            // 触发图片加载任务,加入任务列表
            loadTasks.Add(uriSource.LoadImageAsync(CancellationToken.None));
            imageSources.Add(uriSource);
        }

        // 等待所有图片加载完成(成功或失败)
        await Task.WhenAll(loadTasks);

        // 更新UI绑定的集合
        Images.Clear();
        foreach (var source in imageSources)
        {
            Images.Add(source);
        }
    }
}

调用时机

在页面的OnAppearing方法中异步调用:

protected override async void OnAppearing()
{
    base.OnAppearing();
    await ((YourViewModel)BindingContext).LoadAndPrepareImagesAsync(yourImageUrls);
}

方案2:通过Image控件的Loaded事件强制刷新

如果不想提前等待所有图片加载完成,可以在图片控件加载时手动重置Source,触发重新加载,这样即使首次下载没触发,也能再次发起请求。

XAML代码

<ListView CachingStrategy="RecycleElement" 
          ItemsSource="{Binding Images}" 
          VerticalOptions="FillAndExpand" 
          HorizontalOptions="FillAndExpand" 
          HasUnevenRows="true" 
          SeparatorColor="Transparent" 
          BackgroundColor="White">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Image Source="{Binding}" 
                       VerticalOptions="FillAndExpand"
                       Loaded="Image_Loaded" />
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

后台代码

private void Image_Loaded(object sender, EventArgs e)
{
    var image = sender as Image;
    if (image?.Source is UriImageSource uriSource)
    {
        // 先清空Source再重新赋值,强制触发加载
        image.Source = null;
        image.Source = uriSource;
    }
}

注意事项

  • 确保你的ViewModel实现了INotifyPropertyChanged,或者使用ObservableCollection(如方案1),这样集合更新时UI能自动刷新。
  • 预加载大量图片时要注意内存占用,可通过SemaphoreSlim控制并发加载的数量,避免内存过载:
    var semaphore = new SemaphoreSlim(5); // 同时加载5张图片
    foreach (var url in imageUrls)
    {
        await semaphore.WaitAsync();
        var uriSource = new UriImageSource { ... };
        loadTasks.Add(uriSource.LoadImageAsync(CancellationToken.None).ContinueWith(_ => semaphore.Release()));
        imageSources.Add(uriSource);
    }
    
  • 不要在主线程同步执行加载操作,必须用异步方法,防止UI卡顿。

内容的提问来源于stack exchange,提问作者t3h Exi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:59:25