You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

显示全屏进度时如何避免ANR问题?

解决全屏同步进度界面的ANR问题

核心原因分析

从你提供的日志来看,ANR触发的本质是主线程被SQLite数据库操作(sqlite3_exec/sqlite3_step)阻塞,系统无法及时处理用户的触摸输入事件,最终触发Input dispatching timed out。即使进度动画在更新,只要主线程被耗时的数据库同步操作占用,就会导致输入事件处理超时。

具体解决方案

1. 强制将所有数据库同步操作移至后台线程

必须保证所有EntityFramework+SQLite的同步逻辑(查询、插入、更新)完全在后台线程执行,主线程仅负责接收进度回调并更新UI(动画、进度文本)。绝对禁止在主线程调用任何SQLite相关API,包括EF上下文的读写操作。

  • 可选用的实现方式:ThreadPoolExecutor、Coroutine(Kotlin)、AsyncTask(注意适配高版本Android)

2. 拦截全屏进度界面的触摸事件

既然同步期间不允许用户操作,直接在全屏进度的根容器(如Dialog/Activity的根View)上拦截所有触摸事件,避免事件进入系统输入分发队列:

  • XML布局方式:给根View添加以下属性
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    
  • 代码方式:重写View的触摸事件方法
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 消费所有触摸事件,不传递也不做额外处理
        return true;
    }
    

3. 优化旧版SQLite EF的操作效率

由于无法升级SQLite版本,针对2.2.6版本做针对性优化:

  • 用批量操作替代单条数据循环处理,减少sqlite3_step调用次数
  • 用事务包裹全部同步操作,避免频繁磁盘IO:
    using (var transaction = dbContext.Database.BeginTransaction())
    {
        // 执行所有同步插入/更新逻辑
        dbContext.SaveChanges();
        transaction.Commit();
    }
    
  • 提前预加载同步所需数据,减少同步过程中的查询操作

4. 系统级触摸屏蔽(备选方案)

如果上述拦截方式仍无效,给当前窗口添加触摸屏蔽Flag:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

同步完成后记得清除Flag:

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

验证方式

同步期间用adb shell dumpsys activity activities检查主线程状态,确认无数据库操作在主线程执行;多次点击进度界面,观察是否再触发ANR日志。

内容的提问来源于stack exchange,提问作者krs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 14:46:19