Android API 28下Realm getInstance方法运行极慢致应用启动慢的解决方案咨询
解决Realm在Android API 28环境下首次
getInstance()耗时过高的可落地优化方案 结合同场景项目的实际调试经验,所有优化都围绕拆解Realm的初始化链路、把耗时操作移出用户感知的启动流程展开,没有玄学技巧,都是可以直接落地的操作:
- 将Realm初始化从App启动关键链路剥离
不要在Application.onCreate()、闪屏页的启动流程中同步调用Realm.getInstance()。很多团队为了“提前备好数据库方便后续查询”,把初始化放在最靠前的启动位置,反而让非关键的数据库操作拖慢了整体启动速度。如果业务不需要应用启动后立刻读取Realm数据,就把初始化挪到主线程空闲时机触发:比如通过MessageQueue.IdleHandler在首帧渲染完成、主线程无其他待处理任务时再调用,或者等用户进入第一个需要读取Realm的页面之前再执行初始化,把这1-2秒的耗时从用户可感知的“启动时间”中移除。 - 精简Realm的Schema加载流程
API 28环境下,Realm首次初始化时的类反射扫描耗时比高版本系统高很多——尤其是当你在构建RealmConfiguration时没有手动指定需要加载的RealmObject类列表,Realm会通过反射扫描整个dex下的所有类来筛选符合要求的数据模型,这一步轻松就能占用1秒以上的时间。对应优化操作:- 手动在Realm配置构建时通过
modules()方法明确指定需要加载的model类集合,删掉所有未使用的RealmObject子类,不要让Realm无差别扫描类路径 - 移除数据模型中没有实际业务作用的
@Index、@PrimaryKey注解,减少首次schema校验的计算量 - 确认ProGuard/R8混淆配置没有遗漏对Realm相关类的keep规则,避免运行时因为类被混淆找不到对应结构,触发额外的反射查找耗时
- 手动在Realm配置构建时通过
- 优化预填充Realm文件的加载逻辑
如果应用使用了存放在assets目录下的预填充Realm数据库文件,首次启动时的文件拷贝、结构hash校验、版本比对是主要的耗时来源:- 保证assets中预填充文件的schema版本、结构和当前代码中的数据模型完全匹配,不要让Realm在首次初始化时就触发结构比对、甚至数据迁移的前置IO操作
- 缩小预填充文件的体积,不要把非必要的测试数据、历史冗余内容打包进预填充文件,减少首次拷贝的IO耗时
- 将首次初始化的IO操作移出主线程
API 28对主线程的磁盘IO调度做了优先级限制,主线程下的文件创建、配置写入操作速度会比子线程慢40%以上。可以在子线程提前完成首次的Realm.getInstance()初始化,等初始化完成后,把当前业务需要的查询结果转成普通的可序列化对象,再切回主线程供UI使用——切记不要把Realm实例本身跨线程传递,Realm实例与绑定线程强关联,跨线程使用会直接抛出运行时错误。 - 启动体验的视觉适配
如果以上优化全部落地后,首次getInstance()的耗时还是无法压到500ms以内,就做启动流程的视觉解耦:闪屏页先正常展示品牌内容、同步完成其他非数据库类的SDK初始化(比如统计、推送),等Realm初始化完成后再跳转到首页,不要让用户盯着加载进度条等待数据库初始化,从体验层面降低用户对“启动慢”的感知。
内容的提问来源于stack exchange,提问作者Ankit Kaswan
相关产品推荐
相关产品推荐

