我正在使用Xamarin,我的SQLite表也包含大量数据。
因为我想避免OnCreate()
中的UIThread问题,我需要异步执行数据库操作。
如果我正确处理这个问题,我正在寻找指导。
第一种方法,我在网上找到了:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.InventoryPreviewMain);
Thread thread = new Thread(() =>
{
SQLiteConnection db = new SQLiteConnection(dpPath);
var table = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass where CategoryID =" + Connection.CategoryID + "");
mItems = new List<InventoryPreviewClass>();
foreach (var item in table)
{
mItems.Add(new InventoryPreviewClass() { InventoryItemID = item.InventoryItemID, InventoryItemName = item.InventoryItemName, InventoryItemPrice = item.InventoryItemPrice });
}
MyListViewAdapterInventory adapter = new MyListViewAdapterInventory(this, Resource.Layout.InventoryPreview, mItems);
mlistview.Adapter = adapter;
});
thread.Start();
第二种方法,使用async
public async void StartTimer()
{
SQLiteConnection db = new SQLiteConnection(dpPath);
var table = db.Query<InventoryPreviewClass>("select * from InventoryPreviewClass where CategoryID =" + Connection.CategoryID + "");
mItems = new List<InventoryPreviewClass>();
foreach (var item in table)
{
mItems.Add(new InventoryPreviewClass() { InventoryItemID = item.InventoryItemID, InventoryItemName = item.InventoryItemName, InventoryItemPrice = item.InventoryItemPrice });
}
MyListViewAdapterInventory adapter = new MyListViewAdapterInventory(this, Resource.Layout.InventoryPreview, mItems);
mlistview.Adapter = adapter;
await Task.Delay(500);
}
两个示例中的哪一个对于保持活动UIthread更安全?有没有其他解决方案可以做到这一点?还有什么可以做的?
答案 0 :(得分:0)
使用Cross-platform SQLite Library制作的@FrankKruger为Xamarin移动应用创建/访问SQLite数据库。
这个库有一个内置的异步连接,所以你永远不必担心再次从UI线程访问数据库!
public async Task StartTimer()
{
mItems = await InventoryPreviewClassDatabase.GetAllInventoryPreviewClassAsync();
MyListViewAdapterInventory adapter = new MyListViewAdapterInventory(this, Resource.Layout.InventoryPreview, mItems);
mlistview.Adapter = adapter;
}
using System;
using System.Threading.Tasks;
using SQLite;
namespace SampleApp
{
public abstract class BaseDatabase
{
#region Constant Fields
static readonly Lazy<SQLiteAsyncConnection> _databaseConnectionHolder = new Lazy<SQLiteAsyncConnection>(() => GetDatabaseConnection());
#endregion
#region Fields
static bool _isInitialized;
#endregion
#region Properties
static SQLiteAsyncConnection DatabaseConnection => _databaseConnectionHolder.Value;
#endregion
#region Methods
protected static async Task<SQLiteAsyncConnection> GetDatabaseConnectionAsync()
{
if (!_isInitialized)
await Initialize().ConfigureAwait(false);
return DatabaseConnection;
}
static async Task Initialize()
{
await DatabaseConnection.CreateTableAsync<InventoryPreviewClass>().ConfigureAwait(false);
_isInitialized = true;
}
SQLiteAsyncConnection GetDatabaseConnection()
{
var sqliteFilename = "YourDatabaseName.db3";
string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); // Documents folder
var path = Path.Combine(documentsPath, sqliteFilename);
var conn = new SQLiteAsyncConnection(path, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache);
return conn;
}
#endregion
}
}
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace SampleApp
{
public abstract class InventoryPreviewClassDatabase : BaseDatabase
{
#region Methods
public static async Task<IList<InventoryPreviewClass>> GetAllInventoryPreviewClassAsync()
{
var databaseConnection = await GetDatabaseConnectionAsync().ConfigureAwait(false);
return await databaseConnection.Table<InventoryPreviewClass>().ToListAsync().ConfigureAwait(false);
}
public static async Task<InventoryPreviewClass> GetInventoryPreviewClassByIDAsync(int id)
{
var databaseConnection = await GetDatabaseConnectionAsync().ConfigureAwait(false);
return await databaseConnection.Table<InventoryPreviewClass>().Where(x => x.ID.Equals(id)).FirstOrDefaultAsync().ConfigureAwait(false);
}
public static async Task<int> SaveInventoryPreviewClassAsync(InventoryPreviewClass inventoryPreview)
{
var databaseConnection = await GetDatabaseConnectionAsync().ConfigureAwait(false);
var isObjectInDatabase = await GetInventoryPreviewClassByIDAsync(inventoryPreview.ID).ConfigureAwait(false) != null;
if (isObjectInDatabase)
return await databaseConnection.UpdateAsync(inventoryPreview).ConfigureAwait(false);
return await databaseConnection.InsertAsync(inventoryPreview).ConfigureAwait(false);
}
public static async Task<int> DeleteItemAsync(OpportunityModel opportunity)
{
var databaseConnection = await GetDatabaseConnectionAsync().ConfigureAwait(false);
return await databaseConnection.DeleteAsync(opportunity).ConfigureAwait(false);
}
public static async Task<int> GetNumberOfRowsAsync()
{
var databaseConnection = await GetDatabaseConnectionAsync().ConfigureAwait(false);
return await databaseConnection.Table<InventoryPreviewClass>().CountAsync().ConfigureAwait(false);
}
#endregion
}
}
此代码的灵感来自this Xamarin.Forms sample app