如何从Firebase Cloud Firestore获取准确布尔值而非数据类构造初始值
问题场景
- 基于Kotlin开发Android应用,定义了数据类作为Firestore的文档映射模型,其中包含名为
isGamePlayed的布尔字段,默认值设为false - Firestore数据库中对应文档的
isGamePlayed字段实际存储值为true - 读取数据到RecyclerView Adapter后,其余字段均能正常获取数据库中的存储值,唯独该布尔字段始终返回
false,和实际存储值不符 - 核心Adapter代码如下:
class OneTwoAdapter( private val oneTwoGames: MutableList<Game> ) : RecyclerView.Adapter<OneTwoViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OneTwoViewHolder { return OneTwoViewHolder( LayoutInflater.from(parent.context) .inflate(R.layout.one_two_games_layout, parent, false) ) } override fun onBindViewHolder(holder: OneTwoViewHolder, position: Int) { val gameDetail = oneTwoGames[position] holder.awayTeamName.text = gameDetail.awayTeam holder.gameDate.text = gameDetail.gameDate holder.league.text = gameDetail.league holder.homeTeamName.text = gameDetail.homeTeam holder.kickOff.text = gameDetail.kickOff holder.outCome.text = gameDetail.outCome Glide.with(holder.itemView.context) .load(gameDetail.homeImageUrl) .into(holder.homeTeamImgUrl) Glide.with(holder.itemView.context) .load(gameDetail.awayImageUrl) .into(holder.awayTeamImgUrl) // 此处Toast输出始终为false,和数据库存储的true不符 Toast.makeText( holder.itemView.context, "Status: ${gameDetail.isGamePlayed}", Toast.LENGTH_SHORT ).show() holder.game = gameDetail } override fun getItemCount(): Int { return oneTwoGames.size } }
问题原因
这是Kotlin布尔属性生成规则和Firestore SDK默认映射逻辑的已知冲突:
- 按照Kotlin的类成员生成规则,以
is为前缀命名的布尔属性,自动生成的getter方法名就是属性名本身(即isGamePlayed()),不会生成常规JavaBean规范的getIsGamePlayed()格式getter - Firestore SDK反序列化做字段匹配时,会把
is开头的getter方法名去掉前缀is,将剩余部分作为要匹配的Firestore字段名——也就是说,它会去Firestore文档里找名为gamePlayed的字段给isGamePlayed属性赋值,完全不会匹配你实际存储的isGamePlayed字段 - 因为匹配不到对应字段,SDK直接使用了你在数据类里给该属性设置的默认值
false,其余字段没有is前缀带来的命名冲突,所以可以正常匹配到同名字段,读取到正确值。
修复方案
任选以下一种方案修改即可解决问题:
- 方案1:用
@PropertyName注解显式指定字段映射关系,强制SDK匹配Firestore中存储的isGamePlayed字段,示例写法:data class Game( // 其余字段保持原有定义不变 @get:PropertyName("isGamePlayed") @set:PropertyName("isGamePlayed") val isGamePlayed: Boolean = false ) - 方案2:统一两端字段命名,去掉属性名的
is前缀,比如将数据类中的属性改名为gamePlayed,同时将Firestore中存储的对应字段名也修改为gamePlayed,保持命名完全一致即可正常映射。
内容的提问来源于stack exchange,提问作者Kevin Kyei
相关产品推荐
相关产品推荐

