Xamarin.Forms页面因System.Reflection.TargetInvocationException崩溃:Microcharts饼图异步加载问题排查
解决Microcharts饼图异步加载后的崩溃问题
看起来你遇到的崩溃是由几个潜在问题共同导致的,我们一步步来排查和修复:
1. 核心问题分析
你的错误提示Method not found: void UIKit.UIGestureRecognizer..ctor()大概率是Microcharts与Xamarin.Forms版本不兼容导致的,加上你的ViewModel没有正确通知UI更新,以及异步操作后的UI线程问题,最终触发了崩溃。
另外,使用async void在Command中会导致无法捕获的异常,这也加剧了问题的排查难度。
2. 分步解决方案
步骤一:修复ViewModel的属性通知与线程问题
你的ExpenditurePieChart是一个只读计算属性,当_chartEntries更新后,UI不会收到任何变更通知。同时,异步操作完成后直接更新UI相关数据,可能不在主线程执行,这在Xamarin.Forms中是不允许的。
修改后的VisualDataViewModel代码:
public class VisualDataViewModel : ViewModelBase { private List<ChartEntry> _chartEntries; public static IChartDraw ChartDraw => DependencyService.Get<IChartDraw>(); public ICommand GetPieChartCommand { get; } private Chart _expenditurePieChart; // 改成可绑定属性,更新时触发通知 public Chart ExpenditurePieChart { get => _expenditurePieChart; set { _expenditurePieChart = value; OnPropertyChanged(); // 确保ViewModelBase已实现INotifyPropertyChanged } } public VisualDataViewModel() { _chartEntries = new List<ChartEntry>(); // 使用异步lambda避免async void的问题 GetPieChartCommand = new Command(async () => await GetPieChartAsync()); } // 改成async Task,便于异常捕获和线程管理 private async Task GetPieChartAsync() { // 在后台线程获取数据 var newEntries = await ChartDraw.DrawSummaryPieChartAsync(); // 回到主线程更新UI相关属性(Xamarin.Forms要求UI操作必须在主线程) Device.BeginInvokeOnMainThread(() => { _chartEntries = newEntries; // 重新创建PieChart实例并通知UI更新 ExpenditurePieChart = new PieChart { Entries = _chartEntries }; }); } }
步骤二:解决Microcharts版本兼容性问题
这个UIKit.UIGestureRecognizer构造函数找不到的错误,通常是因为Microcharts的旧版本与你当前使用的Xamarin.Forms版本不兼容。
- 打开NuGet包管理器,更新Microcharts和Microcharts.Forms到最新稳定版
- 确保你的Xamarin.Forms版本与Microcharts版本匹配(比如Xamarin.Forms 5.x对应Microcharts 0.18.x及以上版本)
- 如果更新后仍有问题,可以尝试降级到与你项目兼容的Microcharts版本
步骤三:验证DependencyService的iOS实现
确保IChartDraw的iOS实现没有线程问题:
- 如果
DrawSummaryPieChartAsync中涉及任何UI操作(虽然不应该),必须放到主线程执行 - 确保该方法返回的
ChartEntry数据是正确的,没有空值或异常数据
3. 额外注意事项
- 避免在Command中使用
async void:它会导致异常无法被全局捕获,改用async Task配合异步lambda - 始终在主线程更新UI:Xamarin.Forms的所有UI操作都必须在主线程执行,
Device.BeginInvokeOnMainThread是最稳妥的方式 - 调试时可以捕获全局异常:在App.xaml.cs中添加
UnhandledException事件处理,便于定位深层问题
内容的提问来源于stack exchange,提问作者Spirit_bird
相关产品推荐
相关产品推荐

