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

CarouselView加载时UI卡顿2-3秒及页面传值优化问询

问题解决与优化建议

一、解决页面跳转卡顿问题

1. 修正数据集合的UI线程操作

你的FilterData方法中,await _dataStore.SearchData(...)使用ConfigureAwait(false)后,后续添加数据的代码会运行在后台线程。而ObservableCollection(包括ObservableRangeCollection)的变更必须在UI线程执行,否则会引发UI卡顿甚至异常。修改如下:

public async Task FilterData()
{
    FilteredData.Clear();
    var filtereddata = await _dataStore.SearchData(Hard, Subject).ConfigureAwait(false);
    
    // 切换回UI线程更新集合,用AddRange替代循环Add提升效率
    MainThread.BeginInvokeOnMainThread(() =>
    {
        FilteredData.AddRange(filtereddata);
    });
}

2. 提前加载数据+加载提示

在第一页点击按钮时先加载数据,完成后再跳转页面,避免跳转后UI卡顿:

第一页按钮点击事件修改

private async void ButtonClick(object sender, EventArgs e)
{
    var vm = (BaseViewModel)BindingContext;
    vm.Hard = HardButtonSelected == Hard;
    vm.Subject = vm.Subject.ToLower();

    // 显示加载弹窗(可替换为ActivityIndicator或自定义弹窗)
    await Application.Current.MainPage.DisplayAlert("加载中", "正在准备数据...", "", cancellationToken: new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token);

    try
    {
        // 提前初始化第二页VM并加载数据
        var secondVm = new DataSelectionViewModel(vm.Hard, vm.Subject);
        await secondVm.LoadData.ExecuteAsync();

        // 数据加载完成后跳转
        await Navigation.PushAsync(new SecondPage(secondVm));
    }
    finally
    {
        // 关闭加载弹窗(对应弹窗的关闭逻辑)
        if (Application.Current.MainPage.Navigation.ModalStack.Count > 0)
            await Application.Current.MainPage.Navigation.PopModalAsync();
    }
}

3. 开启CarouselView虚拟化

减少初始加载的UI元素数量,提升渲染速度:

<CarouselView ItemsSource="{Binding FilteredData}"
              EnableVirtualization="True"
              VirtualizationStrategy="Recycling">
    <!-- 你的DataTemplate -->
</CarouselView>

二、优化页面间参数传递方式

1. ViewModel构造函数传参(推荐)

让第二页ViewModel通过构造函数接收参数,避免页面构造时手动赋值:

第二页ViewModel修改

public class DataSelectionViewModel : BaseViewModel
{
    public ObservableRangeCollection<Items> FilteredData { get; set; }
    private readonly IDataStore _dataStore;

    // 新增带参数的构造函数
    public DataSelectionViewModel(bool hard, string subject)
    {
        _dataStore = DependencyService.Get<IDataStore>();
        Hard = hard;
        Subject = subject;
        LoadData = new AsyncAwaitBestPractices.MVVM.AsyncCommand(FilterData);
        FilteredData = new ObservableRangeCollection<Items>();
    }

    public async Task FilterData()
    {
        FilteredData.Clear();
        var filtereddata = await _dataStore.SearchData(Hard, Subject).ConfigureAwait(false);
        
        MainThread.BeginInvokeOnMainThread(() =>
        {
            FilteredData.AddRange(filtereddata);
        });
    }  
}

2. 页面直接接收ViewModel

修改第二页构造函数,直接传入ViewModel并设置绑定上下文:

第二页C#代码修改

public partial class SecondPage : ContentPage
{
    public SecondPage(DataSelectionViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        // 移除原有的加载逻辑,数据已提前加载完成
    }
}

3. 移除XAML中的ViewModel实例化

因为已通过构造函数传入ViewModel,删除XAML中绑定上下文的声明:

<!-- 移除以下代码 -->
<!-- <ContentPage.BindingContext>
    <db:DataSelectionViewModel/>
</ContentPage.BindingContext> -->

这种方式符合MVVM模式,降低代码耦合度,同时避免重复赋值的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:10:40