CoroutineWorker调用Firestore时出现OutOfMemoryError问题排查
Firestore CoroutineWorker 触发 OutOfMemoryError 问题
应用通过CoroutineWorker实现每24小时在后台从Firestore获取数据,触发条件为设备充电且网络状态良好。多数用户使用正常,但小部分用户在调用collection.get()时出现OutOfMemoryError。
崩溃分布数据
- 48%的崩溃发生在Pixel机型(与市场占比不符),49%发生在三星机型
- 46%的崩溃出现在Android 13系统,41%出现在Android 12系统
崩溃日志
Fatal Exception: java.lang.OutOfMemoryError: Firestore (24.2.2) ran out of memory. Check your queries to make sure they are not loading an excessive amount of data. at com.google.firebase.firestore.util.AsyncQueue.lambda$panic$3(AsyncQueue.java:529) at com.google.firebase.firestore.util.AsyncQueue(AsyncQueue.java) at com.google.firebase.firestore.util.AsyncQueue$$InternalSyntheticLambda$0.run(AsyncQueue.java:2) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8741) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
CoroutineWorker 实现代码
@HiltWorker class DatabaseSyncWorker @AssistedInject constructor( @Assisted val context: Context, @Assisted workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) { override suspend fun doWork(): Result { // Crash Log here are display on firebase crashlytics val result = FirebaseFirestore.getInstance().collection("event") .orderBy("updated", Query.Direction.ASCENDING) .whereArrayContains("some_array_key", "some_array_value") .limit(10) .get().await().documents // Crash Log here are NOT display on firebase crashlytics // Doing something with that data here return Result.success() } companion object { const val TAG = "DatabaseSyncWorker" fun startIfNeeded(context: Context) { val constraintBuilder = Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresBatteryNotLow(true) .setRequiresCharging(true) val constraints = constraintBuilder.build() val periodicWorkRequest = PeriodicWorkRequest.Builder(DatabaseSyncWorker::class.java, 24, TimeUnit.HOURS) .setConstraints(constraints) .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest) } } }
已尝试的解决措施
- 减少单次请求的数据量,实现分页逻辑
- 将每页请求数据量限制为10条,但首次请求时依然触发崩溃
内容的提问来源于stack exchange,提问作者Samuel Terroitin
相关产品推荐
相关产品推荐

