Xamarin 选项卡式表单应用程序模板:微调器不停止,异步任务无效
Xamarin Tabbed Forms App Template: Spinner Does Not Stop, Async Task Void
更新: 这不会发生在 Android 设备或 Android 模拟器上;这是 iOS 设备和 iOS 模拟器特定的错误。
我是 运行 Mac 上的一个开箱即用的模板。要测试自己,您只需转到 Visual Studio:
- 文件
- 新解决方案
- 多平台:应用程序
- 选项卡式表单应用程序
在 iPhone 设备或 iPhone 模拟器上 运行 时,列表顶部的微调器 不会停止旋转 .我怀疑这是由于共享表单项目中的这段代码造成的:
public class ItemsViewModel : BaseViewModel
{
public ObservableCollection<Item> Items { get; set; }
public Command LoadItemsCommand { get; set; }
public ItemsViewModel()
{
Title = "Browse";
Items = new ObservableCollection<Item>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
MessagingCenter.Subscribe<NewItemPage, Item>(this, "AddItem", async (obj, item) =>
{
var newItem = item as Item;
Items.Add(newItem);
await DataStore.AddItemAsync(newItem);
});
}
async Task ExecuteLoadItemsCommand()
{
if (IsBusy)
return;
IsBusy = true;
try
{
Items.Clear();
var items = await DataStore.GetItemsAsync(true);
foreach (var item in items)
{
Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
具体来说,LoadItemsCommand = new Command(async () => await ExecuteLoadItemCommand())
连同方法签名将其视为 async Task<void>
。
虽然调用 Tasks as void 是一个很大的问题 no-no 因为除其他原因外,CLR 状态机无法对任务?此外,此任务更改的任何被某些代表监视的内容,值得注意的 IsBusy
,都不会受到影响吗?
来自BaseViewModel.cs:
public class BaseViewModel : INotifyPropertyChanged
{
public IDataStore<Item> DataStore => DependencyService.Get<IDataStore<Item>>();
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
...
}
从视图来看,具体是spinner控件,ItemsPage.xaml:
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
MacOS: 10.15.2,
Visual Studio 对于 Mac: 8.3.10(构建 2),
Xcode: 11.3 (11C29),
iOS 模拟器: 11.3 (SimulatorApp-912.5 SimulatorKit-570.3 CoreSimulator-681.17)
在表单和 iOS 项目中更新以下内容后,
- Xamarin.Forms (4.2.0.709249) -> (4.4.0.991265)
- Xamarin.Essentials
(1.2.0) -> (1.3.1)
加载列表后,微调器现在停止旋转。应该注意的是,在创建这些项目时,尽管 Visual Studio 是最新的,它还是选择使用过时的 NuGet 包创建所述项目。
更新: 这不会发生在 Android 设备或 Android 模拟器上;这是 iOS 设备和 iOS 模拟器特定的错误。
我是 运行 Mac 上的一个开箱即用的模板。要测试自己,您只需转到 Visual Studio:
- 文件
- 新解决方案
- 多平台:应用程序
- 选项卡式表单应用程序
在 iPhone 设备或 iPhone 模拟器上 运行 时,列表顶部的微调器 不会停止旋转 .我怀疑这是由于共享表单项目中的这段代码造成的:
public class ItemsViewModel : BaseViewModel
{
public ObservableCollection<Item> Items { get; set; }
public Command LoadItemsCommand { get; set; }
public ItemsViewModel()
{
Title = "Browse";
Items = new ObservableCollection<Item>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
MessagingCenter.Subscribe<NewItemPage, Item>(this, "AddItem", async (obj, item) =>
{
var newItem = item as Item;
Items.Add(newItem);
await DataStore.AddItemAsync(newItem);
});
}
async Task ExecuteLoadItemsCommand()
{
if (IsBusy)
return;
IsBusy = true;
try
{
Items.Clear();
var items = await DataStore.GetItemsAsync(true);
foreach (var item in items)
{
Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
具体来说,LoadItemsCommand = new Command(async () => await ExecuteLoadItemCommand())
连同方法签名将其视为 async Task<void>
。
虽然调用 Tasks as void 是一个很大的问题 no-no 因为除其他原因外,CLR 状态机无法对任务?此外,此任务更改的任何被某些代表监视的内容,值得注意的 IsBusy
,都不会受到影响吗?
来自BaseViewModel.cs:
public class BaseViewModel : INotifyPropertyChanged
{
public IDataStore<Item> DataStore => DependencyService.Get<IDataStore<Item>>();
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
...
}
从视图来看,具体是spinner控件,ItemsPage.xaml:
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
MacOS: 10.15.2, Visual Studio 对于 Mac: 8.3.10(构建 2), Xcode: 11.3 (11C29), iOS 模拟器: 11.3 (SimulatorApp-912.5 SimulatorKit-570.3 CoreSimulator-681.17)
在表单和 iOS 项目中更新以下内容后,
- Xamarin.Forms (4.2.0.709249) -> (4.4.0.991265)
- Xamarin.Essentials (1.2.0) -> (1.3.1)
加载列表后,微调器现在停止旋转。应该注意的是,在创建这些项目时,尽管 Visual Studio 是最新的,它还是选择使用过时的 NuGet 包创建所述项目。