Firebase数据库读取部分字段为NULL的问题求助
问题排查与解决方案
看了你的代码和日志输出,核心问题非常明确:Firebase Realtime Database的字段名和你的user_post实体类属性名不匹配,导致Firebase的ClassMapper无法正确将数据库中的字段映射到实体类的属性上,这就是为什么大部分字段返回NULL的原因。
具体不匹配的字段对应关系
从警告日志和代码对比就能看出来:
- 数据库中存储的是
artist,但实体类里对应的属性是song_artist - 数据库中存储的是
user_name,但实体类里对应的属性是username - 数据库中存储的是
profile_image,但实体类里对应的属性是image - 另外你的实体类中
image的setter方法是setUserImage,而不是标准的setImage,这也会导致映射失败
解决方案(二选一即可)
方案1:修改实体类,添加字段映射注解(推荐,不用改数据库存储结构)
使用Firebase的@PropertyName注解,明确指定实体类属性对应的数据库字段名,同时修正setter方法名称:
import com.google.firebase.database.PropertyName; public class user_post { private String username; private String song_name; private String song_artist; private String user_comment; private String image; public user_post(){ // Firebase需要空构造函数 } public user_post(String username, String song_name, String song_artist, String user_comment,String image){ this.username = username; this.song_name = song_name; this.song_artist = song_artist; this.user_comment = user_comment; this.image = image; } @PropertyName("user_name") // 指定对应数据库的user_name字段 public String getUsername() { return username; } @PropertyName("user_name") public void setUsername(String username) { this.username = username; } public String getSong_name() { return song_name; } public void setSong_name(String song_name) { this.song_name = song_name; } @PropertyName("artist") // 指定对应数据库的artist字段 public String getSong_artist() { return song_artist; } @PropertyName("artist") public void setSong_artist(String song_artist) { this.song_artist = song_artist; } public String getUser_comment() { return user_comment; } public void setUser_comment(String user_comment) { this.user_comment = user_comment; } @PropertyName("profile_image") // 指定对应数据库的profile_image字段 public String getImage() { return image; } @PropertyName("profile_image") public void setImage(String image) { // 修正setter方法名称为setImage this.image = image; } }
方案2:修改发布数据的代码,让字段名和实体类属性一致
如果你不想修改实体类,那可以调整post_status方法中的字段名,和实体类的属性名保持统一:
public void post_status(){ String full_song = song; final String song_name = full_song.split("//")[0]; final String song_Artist = full_song.split("//")[1]; final DatabaseReference db_post = DB_NewPost.push(); if (song_name != null && song_Artist !=null && user_name != null && profile_image != null) { final ProgressDialog progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("Posting..."); progressDialog.show(); // 注意这里的字段名改成和实体类属性一致的 db_post.child("song_artist").setValue(song_Artist); db_post.child("song_name").setValue(song_name); db_post.child("image").setValue(profile_image); db_post.child("username").setValue(user_name); db_post.child("user_comment").setValue("Test Comment"); db_post.child("user_ID").setValue(user.getUid()).addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { progressDialog.dismiss(); } }); // 注意:这里不需要addValueEventListener,你原来的写法会导致每次数据变化都重复插入,直接setValue即可! } else { CafeBar.builder(MainActivity.this) .duration(CafeBar.Duration.MEDIUM) .content("Post canceled, make sure all the values are set") .maxLines(4) .theme(CafeBarTheme.Custom(Color.parseColor("#E65100"))) .show(); } }
额外提醒
你原来的post_status方法里有个小问题:不需要添加DB_NewPost.addValueEventListener,这个监听会导致每次数据库中DB_NewPost节点数据变化时,都会重复执行插入操作,直接调用db_post.child(...).setValue(...)即可完成数据发布,去掉那个监听能避免不必要的重复插入。
内容的提问来源于stack exchange,提问作者XerXes
相关产品推荐
相关产品推荐

