我以前遇到过这个问题,在遵循本教程后,在 Service.cs 文件中调用 db.CreateTableAsync 之后,我的整个应用程序冻结了。使用 这个解决方案修复此问题后,应用程序停止冻结,但 CreateTableAsync 似乎可以什么都没有,只是中断了 Init 任务和 AddPin 任务。在同一运行时,如果我尝试多次运行 AddPin 任务,第一次 CreateTableAsync 将中断,并且在初始之后连续多次,将调用 AddPin 的其余部分(因为 db != null),值得注意的是无论我运行 AddPin 多少次,id 都不会增加。
厕所.cs
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dook.Model
{
public class Restroom
{
[SQLite.PrimaryKey, SQLite.AutoIncrement]
[Column("Id")]
public int Id { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Address")]
public string Address { get; set; }
[Column("Username")]
public string Username { get; set; }
[Column("Location")]
public Location PinLocation { get; set; }
}
}
RestroomService.cs
using Dook.Model;
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dook.Services
{
public static class RestroomService
{
static SQLiteAsyncConnection db;
static async Task InitAsync()
{
if(db != null)
return;
var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyData.db");
db = new SQLiteAsyncConnection(databasePath);
await db.CreateTableAsync<Restroom>();
Debug.WriteLine("Bruh");
}
public static async Task AddPinAsync(string name, string address, string username, Location location)
{
await InitAsync();
var restroom = new Restroom
{
Name = name,
Address = address,
Username = username,
PinLocation = location
};
var id = await db.InsertAsync(restroom);
}
public static async Task RemovePinAsync(int id)
{
await InitAsync();
await db.DeleteAsync<Restroom>(id);
}
public static async Task<IEnumerable<Restroom>> GetPinAsync()
{
await InitAsync();
var restroom = await db.Table<Restroom>().ToListAsync();
return restroom;
}
}
}
MainPage.xaml.cs
namespace Dook;
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using System.Diagnostics;
using Map = Microsoft.Maui.Controls.Maps.Map;
using Dook.ViewModel;
using Dook.Model;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
MoveMapLocation();
}
private void GoToLocation_Button(object sender, EventArgs e)
{
MoveMapLocation();
}
private void OnMapClicked(object sender, MapClickedEventArgs e)
{
var vm = (MainViewModel)this.BindingContext;
if (vm.AddCommand.CanExecute(e.Location))
vm.AddCommand.ExecuteAsync(e.Location);
}
private void RefreshButton_Clicked(object sender, EventArgs e)
{
var vm = (MainViewModel)this.BindingContext;
vm.RefreshCommand.ExecuteAsync();
}
private void MoveMapLocation()
{
//Function to avoid boilerplate code
MapSpan mapSpan = new MapSpan(MainViewModel.GetLocation(), 0.01, 0.01);
mainmap.MoveToRegion(mapSpan);
}
}
主页.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodel="clr-namespace:Dook.ViewModel"
x:DataType="viewmodel:MainViewModel"
xmlns:maps="clr-namespace:Microsoft.Maui.Controls.Maps;assembly=Microsoft.Maui.Controls.Maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:model="clr-namespace:Dook.Model"
x:Class="Dook.MainPage"
Title="{Binding Title}"
Shell.NavBarIsVisible="False">
<ContentPage.BindingContext>
<viewmodel:MainViewModel />
</ContentPage.BindingContext>
<Grid
Margin="0"
RowDefinitions="*, Auto"
ColumnDefinitions="*">
<maps:Map
x:Name="mainmap"
MapType="Street"
IsShowingUser="True"
x:FieldModifier="public"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
IsVisible="True"
IsEnabled="True"
Grid.Row="0"
MapClicked="OnMapClicked"
ItemsSource="{Binding Restroom}">
<maps:Map.ItemTemplate>
<DataTemplate x:DataType="model:Restroom">
<maps:Pin
Label="{Binding Name}"
Address="{Binding Address}"
Type="Generic"
Location="{Binding PinLocation}"/>
</DataTemplate>
</maps:Map.ItemTemplate>
</maps:Map>
<Button
Text="Refresh"
IsEnabled="{Binding IsNotBusy}"
Clicked="RefreshButton_Clicked"
Margin="5"
VerticalOptions="Center"
HorizontalOptions="Start"
Grid.Row="1"/>
<ImageButton
Source="feather_navigation_icon.png"
Aspect="AspectFill"
Clicked="GoToLocation_Button"
IsEnabled="{Binding IsNotBusy}"
Margin="20"
VerticalOptions="End"
HorizontalOptions="End"
WidthRequest="13"
HeightRequest="13"
BackgroundColor="Transparent"
CornerRadius="10"
Grid.Row="0"/>
</Grid>
</ContentPage>
MainViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
using Dook.Model;
using Dook.Services;
using MvvmHelpers;
using MvvmHelpers.Commands;
using CommunityToolkit.Maui.Core.Extensions;
namespace Dook.ViewModel
{
public class MainViewModel : BaseViewModel
{
public ObservableRangeCollection<Restroom> Restroom { get; set; }
public AsyncCommand RefreshCommand { get; }
public AsyncCommand<Location> AddCommand { get; }
public AsyncCommand<Restroom> RemoveCommand { get; }
public MainViewModel()
{
Title = "Map Controller";
Restroom = new ObservableRangeCollection<Restroom>();
AddCommand = new AsyncCommand<Location>(AddAsync);
RemoveCommand = new AsyncCommand<Restroom>(RemoveAsync);
RefreshCommand = new AsyncCommand(RefreshAsync);
}
async Task AddAsync(Location currentLocation)
{
var name = await App.Current.MainPage.DisplayPromptAsync("Location Name", "Name of Location");
// var address = "Latitude: {pinlocation.Latitude}, Longitude: {pinlocation.Longitude}, Altitude: {location.Altitude}";
var address = "test";
var username = await App.Current.MainPage.DisplayPromptAsync("Username", "Username of Toilet Adder");
var location = currentLocation;
if(name == null || address == null || username == null) { return; }
await RestroomService.AddPinAsync(name, address, username, location);
await RefreshAsync();
}
async Task RemoveAsync(Restroom restroom)
{
await RestroomService.RemovePinAsync(restroom.Id);
await RefreshAsync();
}
async Task RefreshAsync()
{
IsBusy = true;
await Task.Delay(2000);
Restroom.Clear();
var restrooms = await RestroomService.GetPinAsync();
Restroom.AddRange(restrooms);
IsBusy = false;
}
public static Location GetLocation()
{
try
{
Location location = new();
location = Geolocation.Default.GetLastKnownLocationAsync().Result;
if (location != null)
return location;
}
catch (Exception ex)
{
Debug.WriteLine($"Unable to get location: {ex.Message}");
Application.Current.MainPage.DisplayAlert("Error!", ex.Message, "OK");
}
return null;
}
}
}
将纬度和经度存储为单独的字段可以解决该问题。