【问题标题】:Android Room Type Converter for Cursor -> List用于光标的 Android 房间类型转换器 -> 列表
【发布时间】:2021-07-06 18:41:01
【问题描述】:

我正在尝试为 List<Pair<Uri,Uri?>> 编写类型转换器:

Query("SELECT $uri, $imageUrl FROM $data WHERE $color IS NULL")
abstract fun findWithMissingColor(): List<Pair<Uri, Uri?>>
@TypeConverter
fun toUriPair(cursor: Cursor?): List<Pair<Uri, Uri?>> {
    return cursor?.let{ generateSequence { if (it.moveToNext()) it else null }.map {
         Pair(
                Uri.parse(it.getString(0)),
                try { Uri.parse(it.getString(1)) } catch (e: Exception) {null}
         )
    }.toList() } ?: emptyList()
}

这大致基于来自here的信息。

但 Room 不认为这是该查询的有效类型转换器:

error: Not sure how to convert a Cursor to this method's return type (java.util.List<kotlin.Pair<android.net.Uri,android.net.Uri>>).
    public abstract java.util.List<kotlin.Pair<android.net.Uri, android.net.Uri>> findWithMissingColor();

【问题讨论】:

    标签: android kotlin android-room


    【解决方案1】:

    您用作基础的答案的核心原则是,如果提取了超过 1 个列,则列名匹配(重复的列名不明确):-

    Room 会自动将方法的参数绑定到绑定参数中。这是通过将参数的名称与绑定参数的名称相匹配来完成的。

    此外,TypeConverter 只能转换单个值:-

    每个转换器方法应接收 1 个参数并具有非 void 返回类型

    示例

    在不考虑您可能已经序列化 URI 和 URL 的情况下,这里有一个示例可以帮助您提取数据,假设 URI 和 URL 是纯字符串。即不需要 TypeConverters。如果使用序列化的 URI 和 URL 和 BLOBS,显然会有所不同。然后你需要一个 TypeConverters 为每个

    该示例基于您的问题中包含的内容,但所解释的内容可能会有所不同。

    MyDataPairMyDataEntity的内部类)相当于元组/对,其成员名称为firstsecond 这些很重要,因为提取时列名必须匹配这些名称(上面提到的第一点)。

    首先是我称为 MyDataEntity 的实体(这可能会有所不同,但基本上是结构 bar String V Blob):-

    @Entity(tableName = MyDataEntity.MYTABLE_TABLE_NAME)
    class MyDataEntity{
    
        /*
            CONSTANTS for COLUMN AND TABLE NAMES
         */
        companion object {
            const val ID_COLUMN_NAME: String = "_id"
            const val URI_COLUMN_NAME: String = "uri"
            const val IMAGEURL_COLUMN_NAME: String = "urlimage"
            const val COLOR_COLUMN_NAME: String = "color"
            const val MYTABLE_TABLE_NAME: String = "mydata"
        }
    
        @PrimaryKey
        @ColumnInfo(name = ID_COLUMN_NAME)
        var id: Long? = null
        @ColumnInfo(name = URI_COLUMN_NAME)
        var uri: String? = null
        @ColumnInfo(name = IMAGEURL_COLUMN_NAME)
        var imageUrl: String? = null
        @ColumnInfo(name = COLOR_COLUMN_NAME)
        var color: Long? = null
    
        constructor()
    
        @Ignore
        constructor(id: Long?,uri: String?,imageurl: String,color: Long?) {
            this.id = id
            this.uri = uri
            this.imageUrl = imageurl
            this.color = color
        }
    
        class MyDataPair(first: String?, second: String?) {
            var first: String? = first
            var second: String? = second
    
            @Ignore
            /* NOT USED/COMPLETE */
            fun getFirstAsUri(): URI {
                /* code here to build URI */
                return URI(first)
            }
            @Ignore
            /* NOT USED/COMPLETE */
            fun getSecondAsUrl(): URL {
                /* code here to build URL */
                return URL(second)
            }
        }
    }
    

    The Dao MyDataDao(包括您的查询和特定的输出列名,以适应 MyDataEntity 中的内部 MyDataPair 类(第一和第二)):-

    @Dao
    interface MyDataDao {
    
        /* For inserting test data */
        @Insert
        fun insertMyDataRow(myDataEntity: MyDataEntity): Long
        /* Efectively your query BUT WITH specific output/result column names to suit the MyDataPair class */
        @Query("SELECT ${MyDataEntity.URI_COLUMN_NAME} AS first,${MyDataEntity.IMAGEURL_COLUMN_NAME} AS second FROM ${MyDataEntity.MYTABLE_TABLE_NAME} WHERE ${MyDataEntity.COLOR_COLUMN_NAME} IS NULL")
        fun findWithMissingColor(): List<MyDataEntity.MyDataPair>
        /* Clear the table for renability */
        @Query("DELETE FROM ${MyDataEntity.MYTABLE_TABLE_NAME}")
        fun clearMyDataEntityTable(): Int
    }
    

    数据库我的数据库

    @Database(entities = [MyDataEntity::class],version = 1)
    abstract class MyDatabase: RoomDatabase() {
        abstract fun getMyDataDao(): MyDataDao
        companion object {
            const val DATABASE_NAME = "mydatabase"
        }
    }
    

    最后是一个 Activity MainActivity 将它们放在一起:-

    class MainActivity : AppCompatActivity() {
    
        lateinit var db: MyDatabase
        lateinit var dao: MyDataDao
        val TAG = "MYDBINFO"
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            db = Room.databaseBuilder(this,MyDatabase::class.java,MyDatabase.DATABASE_NAME)
                .allowMainThreadQueries()
                .build()
            dao = db.getMyDataDao()
            var deleted_rows = dao.clearMyDataEntityTable()
    
            /* CLEAR ANY EXIST DATALOAD AND LOAD SOME DATA */
            Log.d(TAG, "$deleted_rows were deleted from the table ${MyDataEntity.MYTABLE_TABLE_NAME}")
            dao.insertMyDataRow(MyDataEntity(null,"uri1","imageurl1", 0x00ffffff))
            dao.insertMyDataRow(MyDataEntity(null,"uri2","imageurl2",null))
            dao.insertMyDataRow(MyDataEntity(null,"uri3","imageurl3",0xAAAAAA))
            dao.insertMyDataRow(MyDataEntity(null,"uri4","imageurl4",null))
            /* EXTRACT ROWS WHERE COLOR IS NULL */
            var results = dao.findWithMissingColor()
            /* WRITE SOME INFO ABOUT THE EXTRACTED DATA TO THE LOG */
            for(mdp: MyDataEntity.MyDataPair in results) {
                Log.d(TAG,"STRING_URI =  ${mdp.first}  STRING_URL = ${mdp.second}")
            }
        }
    }
    
    • 为了方便和简洁运行主线程
    • 插入 4 行 2 颜色为 NULL,2 行颜色为 NULL

    结果来自运行

    运行后的数据库是(根据 Database Inspector):-

    日志包括:-

    2021-04-12 12:29:18.085 D/MYDBINFO: 4 were deleted from the table mydata
    2021-04-12 12:29:18.099 D/MYDBINFO: STRING_URI =  uri2  STRING_URL = imageurl2
    2021-04-12 12:29:18.099 D/MYDBINFO: STRING_URI =  uri4  STRING_URL = imageurl4
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 2018-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 2018-07-06
      相关资源
      最近更新 更多