Room 2.5.2 运行时崩溃 - NoSuchFieldError:没有 SQLiteStatement 类型的实例字段 mDelegate

问题描述 投票:0回答:1

我正在尝试将我正在开发的 Android 应用程序上的 Room 数据库从版本 2.4.3 更新到 2.5.2,这些是我的 gradle.build 文件中的 Room 依赖项

dependencies {
    val room_version = "2.5.2"
    implementation("androidx.room:room-runtime:$room_version")
    implementation("androidx.room:room-ktx:$room_version")
    kapt("androidx.room:room-compiler:$room_version")

}

应用程序编译并构建成功,但不幸的是在运行时,当使用查询时,Room 崩溃并出现 NoSuchFieldError 错误。

FATAL EXCEPTION: Thread-29
Process: my.app, PID: 29657
java.lang.NoSuchFieldError: No instance field mDelegate of type Landroid/database/sqlite/SQLiteStatement; in class Landroidx/sqlite/db/framework/FrameworkSQLiteStatement; or its superclasses (declaration of 'androidx.sqlite.db.framework.FrameworkSQLiteStatement' appears in /data/app/~~8vd8qCDSVAv==/my.app/base.apk)
at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(Unknown Source:0)
at androidx.room.EntityInsertionAdapter.insertAndReturnId(EntityInsertionAdapter.kt:102)

快速查看源代码后,我的代码似乎位于堆栈跟踪行

at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(Unknown Source:0)

指向这个类

package androidx.sqlite.db.framework

import android.database.sqlite.SQLiteStatement
import androidx.sqlite.db.SupportSQLiteStatement

/**
 * Delegates all calls to a [SQLiteStatement].
 *
 * @constructor Creates a wrapper around a framework [SQLiteStatement].
 *
 * @param delegate The SQLiteStatement to delegate calls to.
 */
internal class FrameworkSQLiteStatement(
    private val delegate: SQLiteStatement
) : FrameworkSQLiteProgram(
    delegate
), SupportSQLiteStatement {
    override fun execute() {
        delegate.execute()
    }

    override fun executeUpdateDelete(): Int {
        return delegate.executeUpdateDelete()
    }

    override fun executeInsert(): Long {
        return delegate.executeInsert()
    }

    override fun simpleQueryForLong(): Long {
        return delegate.simpleQueryForLong()
    }

    override fun simpleQueryForString(): String? {
        return delegate.simpleQueryForString()
    }
}

可以在这里找到 https://androidx.tech/artifacts/sqlite/sqlite-framework/2.3.0-source/androidx/sqlite/db/framework/FrameworkSQLiteStatement.kt.html

这是 androidx.sqlite:sqlite-framework 依赖版本 2.3.0 的源代码。

根据堆栈跟踪日志,Room 似乎指向基于“mDelegate”字段的旧版本。

https://androidx.tech/artifacts/sqlite/sqlite-framework/2.0.1-source/androidx/sqlite/db/framework/FrameworkSQLiteStatement.java.html

这是 androidx.sqlite:sqlite-framework 版本 2.0.1,其中有一个定义为“mDelegate”的字段。

看起来(如果我错了,请纠正我)Room 库在运行时正在从旧版本的 sqlite 中查找类,或者整个 Room 库及其对 sqlite 的传递依赖项都在运行旧版本在运行时,尽管我在编译时实际拥有的内容。

尝试到处寻找可能导致此问题的原因。什么也没发生。

我观察到的事情:

  • 我目前使用的是 Room 版本 2.4.3,该问题开始出现在版本 2.5.0-beta01 上。我慢慢地从 Android 网站上增加版本号,直到我准确地找到它开始出现的位置。我测试了 2.5.0-beta01 和 2.5.2 之间的每个版本,它们都会导致运行时崩溃。

  • 该问题存在于不同OEM的不同手机中,与特定设备无关。

  • 我运行了 gradle 依赖关系树任务,没有发现任何库使用任何可传递的 room/sqlite 依赖关系!

我尝试过的事情:

  • 我尝试更新所有其他 Android 依赖项,至少是其中的大多数(我的项目有几十个依赖项)。我尝试更新所有 Androidx 和 Kotlin 依赖项,并尝试注释掉大部分第三方依赖项。

  • 我尝试从 kapt() 切换到 ksp() ,然后再切换到 room 编译器依赖项的 commentProcessor() 。没关系。

  • 我尝试通过严格的 gradle.build 文件中的 {} 和 resolutionStrategy{} 块强制 Room 和 sqlite 版本。

      configurations.all {
      resolutionStrategy {
          force("androidx.room:room-runtime:2.5.2")
          force("androidx.room:room-ktx:2.5.2")
          force("androidx.room:room-compiler:2.5.2")
      force("androidx.sqlite:sqlite-framework:2.3.1")
      }
      }
    
    
      dependencies {
      implementation("androidx.room:room-runtime") {
          version {
              strictly("2.5.2")
              }
          }
      // etc for the rest of the room and sqlite dependencies 
      }
    

由于这个问题,我现在被迫陷入旧版本的 Room(可能会无限期地),并且像 Workmanager 2.8.1 这样隐式/传递依赖于早于 2.5.0 的 Room 版本的库无法更新,因为我还需要用它来更新 Room。

android sqlite android-room androidx
1个回答
0
投票

看起来这次崩溃的原因是旧版本的

sentry
库。 我将应用程序的
build.gradle
中的哨兵库更新到最后一个并且所有工作正常。

plugins {
...
id "io.sentry.android.gradle" version "3.12.0"

}

© www.soinside.com 2019 - 2024. All rights reserved.