加载数据库数据填充ListView时应用无响应问题排查
问题描述
尝试从数据库获取数据填充ListView,打开页面时应用冻结并弹出‘Application is not responding’错误,但日志中未捕获到异常信息。
相关代码
ContentPage 代码
public PollsPage() { InitializeComponent(); getPolls(); } public async Task getPolls() { Database.SmartYardDB db = new Database.SmartYardDB(); if(db.getNotAnsweredPolls().Result != null) lvPolls.ItemsSource = (IList<Models.Tables.Polls>)db.getNotAnsweredPolls().Result; }
Database 类中 getNotAnsweredPolls 方法
public SQLiteAsyncConnection db; public async Task init() { if (db is not null) { return; } db = new SQLiteAsyncConnection(Constants.Database.DatabasePath, Constants.Database.Flags); await db.CreateTableAsync<Models.Tables.Users>(); await db.CreateTableAsync<Models.Tables.Messages>(); await db.CreateTableAsync<Models.Tables.Polls>(); } public async Task<List<Models.Tables.Polls>> getNotAnsweredPolls() { await init(); return await db.Table<Models.Tables.Polls>().Where( x => x.userAnswer != Constants.Database.POLLS_USERANSWER_NOTANSWERED && x.status == Constants.Database.POLLS_STATUS_ACTIVE).ToListAsync(); }
数据库路径获取代码
public static string DatabasePath => Path.Combine(FileSystem.AppDataDirectory, DB_NAME);
AndroidManifest 配置
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> </manifest>
问题原因及解决方法
核心问题:死锁
构造函数中直接调用异步方法getPolls(),且方法内用.Result同步等待异步任务,导致死锁:
- UI线程调用
.Result会阻塞,等待异步任务完成 - 异步任务中的
await需要回到UI线程继续执行,但UI线程已被阻塞,形成循环等待,最终触发ANR错误
修复步骤
改用生命周期方法执行异步操作
替换构造函数中的调用,在OnAppearing中用await正确等待:public PollsPage() { InitializeComponent(); } protected override async void OnAppearing() { base.OnAppearing(); await getPolls(); }全程使用异步等待,移除
.Result
修改getPolls()方法,避免同步阻塞,同时减少重复数据库查询:public async Task getPolls() { Database.SmartYardDB db = new Database.SmartYardDB(); var polls = await db.getNotAnsweredPolls(); if(polls != null) lvPolls.ItemsSource = polls; }权限优化(可选)
当前数据库路径使用FileSystem.AppDataDirectory,无需外部存储权限,可移除READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE、MANAGE_EXTERNAL_STORAGE权限,避免不必要的权限申请流程。
内容的提问来源于stack exchange,提问作者StudyAndroid
相关产品推荐
相关产品推荐

