fix crash of sqlite in release mode

This commit is contained in:
gaoyuan 2022-03-12 01:08:17 +08:00
parent 51ac42b9fc
commit c43bfb51be
7 changed files with 118 additions and 103 deletions

View File

@ -30,7 +30,6 @@ namespace Billing
InitResources(); InitResources();
MainPage = new MainShell(); MainPage = new MainShell();
//Shell.Current.GoToAsync("//Splash");
} }
protected override void OnStart() protected override void OnStart()
@ -39,12 +38,13 @@ namespace Billing
Helper.Debug($"cache folder: {StoreHelper.CacheFolder}"); Helper.Debug($"cache folder: {StoreHelper.CacheFolder}");
} }
internal static async Task InitializeData() public static async Task InitializeData()
{ {
var instance = await StoreHelper.Instance;
await Task.WhenAll( await Task.WhenAll(
Task.Run(async () => accounts = await StoreHelper.GetAccountsAsync()), Task.Run(async () => accounts = await instance.GetListAsync<Account>()),
Task.Run(async () => categories = await StoreHelper.GetCategoriesAsync()), Task.Run(async () => categories = await instance.GetListAsync<Category>()),
Task.Run(async () => bills = await StoreHelper.GetBillsAsync())); Task.Run(async () => bills = await instance.GetListAsync<Bill>()));
} }
protected override void OnResume() protected override void OnResume()

View File

@ -39,6 +39,7 @@ namespace Billing
public static void Error(string category, Exception ex) public static void Error(string category, Exception ex)
{ {
MainThread.BeginInvokeOnMainThread(async () => await Shell.Current.DisplayAlert(category, ex.ToString(), "Ok"));
} }
public static void Error(string category, string message) public static void Error(string category, string message)
@ -139,15 +140,10 @@ namespace Billing
public delegate void PropertyValueChanged<TResult, TOwner>(TOwner obj, TResult old, TResult @new); public delegate void PropertyValueChanged<TResult, TOwner>(TOwner obj, TResult old, TResult @new);
} }
internal class AsyncLazy<T> public class AsyncLazy<T>
{ {
private readonly Lazy<Task<T>> instance; private readonly Lazy<Task<T>> instance;
public AsyncLazy(Func<T> factory)
{
instance = new Lazy<Task<T>>(() => Task.Run(factory));
}
public AsyncLazy(Func<Task<T>> factory) public AsyncLazy(Func<Task<T>> factory)
{ {
instance = new Lazy<Task<T>>(() => Task.Run(factory)); instance = new Lazy<Task<T>>(() => Task.Run(factory));

View File

@ -28,68 +28,97 @@ namespace Billing.Store
{ {
return false; return false;
} }
if (database != null) try
{ {
await database.CloseAsync(); if (database != null)
{
await database.CloseAsync();
}
}
catch (Exception ex)
{
Helper.Error("database.close", ex);
}
try
{
File.Copy(file, path, true);
}
catch (Exception ex)
{
Helper.Error("file.import", ex);
}
try
{
database = new SQLiteAsyncConnection(path,
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
}
catch (Exception ex)
{
Helper.Error("database.connect", ex);
} }
File.Copy(file, path, true);
database = new SQLiteAsyncConnection(path,
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
return true; return true;
} }
private static readonly AsyncLazy<StoreHelper> Instance = new(async () => public static readonly AsyncLazy<StoreHelper> Instance = new(async () =>
{ {
var instance = new StoreHelper(); var instance = new StoreHelper();
await database.CreateTablesAsync<Category, Account, Bill>(); try
var count = await database.ExecuteScalarAsync<int>("SELECT COUNT(Id) FROM [Category]");
if (count <= 0)
{ {
// init categories await database.CreateTablesAsync<Category, Account, Bill>();
await database.InsertAllAsync(new List<Category> } catch (Exception ex)
{
Helper.Error("database.init.table", ex);
}
try
{
var count = await database.ExecuteScalarAsync<int>("SELECT COUNT(Id) FROM [Category]");
if (count <= 0)
{ {
// sample categories // init categories
new() { Name = Resource.Clothing, Icon = "clothes" }, await database.InsertAllAsync(new List<Category>
new() { Name = Resource.Food, Icon = "food" }, {
new() { Name = Resource.Daily, Icon = "daily" }, // sample categories
new() { Name = Resource.Trans, Icon = "trans" }, new() { Name = Resource.Clothing, Icon = "clothes" },
new() { Name = Resource.Entertainment, Icon = "face" }, new() { Name = Resource.Food, Icon = "food" },
new() { Name = Resource.Learn, Icon = "learn" }, new() { Name = Resource.Daily, Icon = "daily" },
new() { Name = Resource.Medical, Icon = "medical" }, new() { Name = Resource.Trans, Icon = "trans" },
new() { Name = Resource.OtherSpending, Icon = "plus" }, new() { Name = Resource.Entertainment, Icon = "face" },
new() { Name = Resource.Learn, Icon = "learn" },
new() { Name = Resource.Medical, Icon = "medical" },
new() { Name = Resource.OtherSpending, Icon = "plus" },
new() { Type = CategoryType.Income, Name = Resource.Earnings, Icon = "#brand#btc" }, new() { Type = CategoryType.Income, Name = Resource.Earnings, Icon = "#brand#btc" },
new() { Type = CategoryType.Income, Name = Resource.OtherIncome, Icon = "plus" }, new() { Type = CategoryType.Income, Name = Resource.OtherIncome, Icon = "plus" },
// sub-categories // sub-categories
new() { ParentId = 1, Name = Resource.Jewellery, Icon = "gem" }, new() { ParentId = 1, Name = Resource.Jewellery, Icon = "gem" },
new() { ParentId = 1, Name = Resource.Cosmetics, Icon = "makeup" }, new() { ParentId = 1, Name = Resource.Cosmetics, Icon = "makeup" },
new() { ParentId = 2, Name = Resource.Brunch, Icon = "brunch" }, new() { ParentId = 2, Name = Resource.Brunch, Icon = "brunch" },
new() { ParentId = 2, Name = Resource.Dinner, Icon = "dinner" }, new() { ParentId = 2, Name = Resource.Dinner, Icon = "dinner" },
new() { ParentId = 2, Name = Resource.Drinks, Icon = "drink" }, new() { ParentId = 2, Name = Resource.Drinks, Icon = "drink" },
new() { ParentId = 2, Name = Resource.Fruit, Icon = "fruit" }, new() { ParentId = 2, Name = Resource.Fruit, Icon = "fruit" },
new() { ParentId = 3, Name = Resource.UtilityBill, Icon = "bill" }, new() { ParentId = 3, Name = Resource.UtilityBill, Icon = "bill" },
new() { ParentId = 3, Name = Resource.PropertyFee, Icon = "fee" }, new() { ParentId = 3, Name = Resource.PropertyFee, Icon = "fee" },
new() { ParentId = 3, Name = Resource.Rent, Icon = "rent" }, new() { ParentId = 3, Name = Resource.Rent, Icon = "rent" },
new() { ParentId = 3, Name = Resource.Maintenance, Icon = "maintenance" }, new() { ParentId = 3, Name = Resource.Maintenance, Icon = "maintenance" },
new() { ParentId = 4, Name = Resource.LightRail, Icon = "rail" }, new() { ParentId = 4, Name = Resource.LightRail, Icon = "rail" },
new() { ParentId = 4, Name = Resource.Taxi, Icon = "taxi" }, new() { ParentId = 4, Name = Resource.Taxi, Icon = "taxi" },
new() { ParentId = 5, Name = Resource.Fitness, Icon = "fitness" }, new() { ParentId = 5, Name = Resource.Fitness, Icon = "fitness" },
new() { ParentId = 5, Name = Resource.Party, Icon = "party" }, new() { ParentId = 5, Name = Resource.Party, Icon = "party" },
new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Salary, Icon = "#brand#buffer" }, new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Salary, Icon = "#brand#buffer" },
new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Bonus, Icon = "dollar" }, new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Bonus, Icon = "dollar" },
}); });
}
}
catch (Exception ex)
{
Helper.Error("database.init.category", ex);
} }
return instance; return instance;
}); });
public static async Task<List<Account>> GetAccountsAsync()
{
var instance = await Instance;
return await instance.GetListAsync<Account>();
}
public static async Task<int> SaveAccountItemAsync(Account account) public static async Task<int> SaveAccountItemAsync(Account account)
{ {
var instance = await Instance; var instance = await Instance;
@ -101,11 +130,6 @@ namespace Billing.Store
return await instance.DeleteItemAsync(account); return await instance.DeleteItemAsync(account);
} }
public static async Task<List<Bill>> GetBillsAsync()
{
var instance = await Instance;
return await instance.GetListAsync<Bill>();
}
public static async Task<int> SaveBillItemAsync(Bill bill) public static async Task<int> SaveBillItemAsync(Bill bill)
{ {
var instance = await Instance; var instance = await Instance;
@ -117,11 +141,6 @@ namespace Billing.Store
return await instance.DeleteItemAsync(bill); return await instance.DeleteItemAsync(bill);
} }
public static async Task<List<Category>> GetCategoriesAsync()
{
var instance = await Instance;
return await instance.GetListAsync<Category>();
}
public static async Task<int> SaveCategoryItemAsync(Category category) public static async Task<int> SaveCategoryItemAsync(Category category)
{ {
var instance = await Instance; var instance = await Instance;
@ -137,10 +156,17 @@ namespace Billing.Store
{ {
if (database == null) if (database == null)
{ {
database = new SQLiteAsyncConnection(DatabasePath, try
SQLiteOpenFlags.ReadWrite | {
SQLiteOpenFlags.Create | database = new SQLiteAsyncConnection(DatabasePath,
SQLiteOpenFlags.SharedCache); SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
}
catch (Exception ex)
{
Helper.Error("database.ctor.connect", ex);
}
} }
} }
@ -178,7 +204,7 @@ namespace Billing.Store
#region Helper #region Helper
private Task<List<T>> GetListAsync<T>() where T : new() public Task<List<T>> GetListAsync<T>() where T : new()
{ {
try try
{ {
@ -191,7 +217,7 @@ namespace Billing.Store
return default; return default;
} }
private Task<int> SaveItemAsync<T>(T item) where T : IIdItem public Task<int> SaveItemAsync<T>(T item) where T : IIdItem
{ {
try try
{ {
@ -211,7 +237,7 @@ namespace Billing.Store
return Task.FromResult(0); return Task.FromResult(0);
} }
private Task<int> DeleteItemAsync<T>(T item) where T : IIdItem public Task<int> DeleteItemAsync<T>(T item) where T : IIdItem
{ {
try try
{ {

View File

@ -60,7 +60,6 @@
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Numerics" /> <Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.10.311" package="org.tsanie.billing" android:installLocation="auto" android:versionCode="10"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0.312" package="org.tsanie.billing" android:installLocation="auto" android:versionCode="11">
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30" /> <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30" />
<application android:label="@string/applabel" android:theme="@style/MainTheme"></application> <application android:label="@string/applabel" android:theme="@style/MainTheme"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

View File

@ -38,6 +38,7 @@
<MtouchLink>None</MtouchLink> <MtouchLink>None</MtouchLink>
<MtouchArch>x86_64</MtouchArch> <MtouchArch>x86_64</MtouchArch>
<CodesignKey>iPhone Distribution</CodesignKey> <CodesignKey>iPhone Distribution</CodesignKey>
<MtouchUseLlvm>true</MtouchUseLlvm>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -64,6 +65,8 @@
<CodesignKey>iPhone Distribution</CodesignKey> <CodesignKey>iPhone Distribution</CodesignKey>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> <CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchLink>SdkOnly</MtouchLink> <MtouchLink>SdkOnly</MtouchLink>
<MtouchInterpreter>-all</MtouchInterpreter>
<MtouchUseLlvm>true</MtouchUseLlvm>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Definition.cs" /> <Compile Include="Definition.cs" />
@ -166,14 +169,13 @@
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="Xamarin.iOS" /> <Reference Include="Xamarin.iOS" />
<Reference Include="System.Numerics" /> <Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microcharts.Forms" Version="0.9.5.9" /> <PackageReference Include="Microcharts.Forms" Version="0.9.5.9" />
<PackageReference Include="SkiaSharp.Views.Forms" Version="2.80.3" /> <PackageReference Include="SkiaSharp.Views.Forms" Version="2.80.3" />
<PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2337" /> <PackageReference Include="Xamarin.Forms" Version="5.0.0.2337" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.1" /> <PackageReference Include="Xamarin.Essentials" Version="1.7.1" />
<PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BundleResource Include="Resources\dollar.png" /> <BundleResource Include="Resources\dollar.png" />
@ -477,14 +479,6 @@
<ItemGroup> <ItemGroup>
<BundleResource Include="Resources\left%403x.png" /> <BundleResource Include="Resources\left%403x.png" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Billing.ShareExtension\Billing.ShareExtension.csproj">
<IsAppExtension>true</IsAppExtension>
<Project>{D4EA6D3A-17E6-4300-80A7-2ED19B738C6B}</Project>
<Name>Billing.ShareExtension</Name>
<ReferenceSourceTarget></ReferenceSourceTarget>
</ProjectReference>
</ItemGroup>
<Import Project="..\..\Billing.Shared\Billing.Shared.projitems" Label="Shared" /> <Import Project="..\..\Billing.Shared\Billing.Shared.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
</Project> </Project>

View File

@ -42,23 +42,23 @@
<string>OpenSans-SemiBold.ttf</string> <string>OpenSans-SemiBold.ttf</string>
</array> </array>
<key>CFBundleDocumentTypes</key> <key>CFBundleDocumentTypes</key>
<array> <array>
<dict> <dict>
<key>CFBundleTypeName</key> <key>CFBundleTypeName</key>
<string>Master SQLite file</string> <string>Master SQLite file</string>
<key>LSItemContentTypes</key> <key>LSItemContentTypes</key>
<array> <array>
<string>public.data</string> <string>public.data</string>
</array> </array>
<key>CFBundleTypeIconFiles</key> <key>CFBundleTypeIconFiles</key>
<array> <array>
<string>Assets.xcassets/AppIcon.appiconset/Icon180</string> <string>Assets.xcassets/AppIcon.appiconset/Icon180</string>
</array> </array>
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>10</string> <string>11</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.10.311</string> <string>1.0.312</string>
</dict> </dict>
</plist> </plist>