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
相关产品推荐
相关产品推荐

