我正在尝试在Android上的Xamarin Forms中使用CrossGeolocator获取设备位置,但是下面的代码抛出了一条Exception,其中包含“无法在未调用Looper.prepare()的线程内创建处理程序”的消息。如何在不阻止UI线程的情况下调用GetPositionAsync?
定位服务
public async Task<Position> GetCurrentLocation(double desiredAccuracy = 100)
{
Position position = null;
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = desiredAccuracy;
var available = await locator.GetIsGeolocationAvailableAsync();
var enabled = await locator.GetIsGeolocationEnabledAsync();
if (!available || !enabled)
{
throw new Exception("Location Error.");
}
position = await locator.GetPositionAsync(TimeSpan.FromSeconds(20), null, true);
}
catch (Exception ex)
{
Device.BeginInvokeOnMainThread(() =>
{
App.Current.MainPage.DisplayAlert("Location Error", ex.Message, "Ok");
});
}
return position;
}
Page.xaml.cs
private ILocationService _location;
private UserAccountViewModel _vm;
public UserAccountPage(UserAccountViewModel viewModel)
{
InitializeComponent();
BindingContext =_vm = viewModel;
var _location = App.Container.Resolve<ILocationService>();
Task.Run(async () => await _location.GetCurrentLocation())
.ContinueWith(r =>
{
var loc = r.Result;
_vm.UserAccount.Latitude= loc?.Latitude;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
如果我在Task.Run之外调用_location.GetCurrentLocation(),它会返回正确的值,但是我无法更新UI。
修改/更新: 我也可以从页面构造函数中调用以下代码,没有任何异常,所以问题必须是Xam.Plugin.Geolocator,我只是找不到关于这个场景的任何信息......
var dataService = App.Container.Resolve<IDataService>();
Task.Run(async () => await dataService.UserAccount.Localisations())
.ContinueWith(result =>
{
_vm.UserAccount.FirstName = result.Result.Count().ToString();
}, TaskScheduler.FromCurrentSynchronizationContext());
解决方法:我将代码移动到ViewModel并删除了Task.Run,然后从页面构造函数中调用了该函数,但我仍然想知道如何使用Task调用此代码。
public async Task UpdateLocation()
{
var _location = App.Container.Resolve<ILocationService>();
var loc = await _location.GetCurrentLocation();
UserAccount.Latitude = loc?.Latitude;
}
答案 0 :(得分:0)
您可以在 OnAppearing 方法中编写该代码。像,
protected override void OnAppearing()
{
var _location = App.Container.Resolve<ILocationService>();
Task.Run(async () => await _location.GetCurrentLocation())
.ContinueWith(r =>
{
var loc = r.Result;
_vm.UserAccount.Latitude= loc?.Latitude;
}, TaskScheduler.FromCurrentSynchronizationContext());
}