Firebase UI - 自定义 SnapshotParser 被编译器跳过
Firebase UI - custom SnapshotParser is skipped by compiler
因此,我正在使用 Firebase UI 从数据库中获取数据。
它看起来像这样:
我想遍历 "messages" 以获取每个 child,并在我的应用程序中将其显示为消息。这就是我的 UserMessage class 的样子:
public class UserMessage {
private String mUserLogin;
private String mUserMessage;
private String mUID;
UserMessage(String userLogin, String userMessage, String uid) {
mUserLogin = userLogin;
mUserMessage = userMessage;
mUID = uid;
}
public String getmUserLogin() {
return mUserLogin;
}
public void setmUserLogin(String mUserLogin) {
this.mUserLogin = mUserLogin;
}
public String getmUserMessage() {
return mUserMessage;
}
public String getmUID() {
return mUID;
}
public void setmUID(String mUID) {
this.mUID = mUID;
}
public void setmUserMessage(String mUserMessage) {
this.mUserMessage = mUserMessage;
}
}
我想通过 FirebaseRecyclerOptions 获取它:
FirebaseRecyclerOptions<UserMessage> options =
new FirebaseRecyclerOptions.Builder<UserMessage>()
.setQuery(firebaseDatabaseModel.getQuery(), new SnapshotParser<UserMessage>() {
@NonNull
@Override
public UserMessage parseSnapshot(@NonNull DataSnapshot snapshot) {
Log.d("snapshot length", String.valueOf(snapshot.getChildrenCount()));
return snapshot.getValue(UserMessage.class);
}
})
.build();
这是我的 firebaseDatabaseModel.getQuery() 方法的样子:
public Query getQuery() {
DatabaseReference messageReference = database.child("messages");
return messageReference.limitToLast(50);
}
这就是我想在我的 FirebaseRecyclerAdapter 中设置数据的方式
class ChatMessagesAdapter extends FirebaseRecyclerAdapter<UserMessage, ChatMessagesAdapter.ChatHolder> {
private UserMessage[] userMessages;
/**
* Initialize a {@link RecyclerView.Adapter} that listens to a Firebase query. See
* {@link FirebaseRecyclerOptions} for configuration options.
*
* @param options
*/
public ChatMessagesAdapter(@NonNull FirebaseRecyclerOptions<UserMessage> options) {
super(options);
userMessages = (UserMessage[]) options.getSnapshots().toArray();
}
@Override
protected void onBindViewHolder(@NonNull ChatHolder holder, int position, @NonNull UserMessage model) {
holder.message.setText(userMessages[position].getmUserMessage());
holder.user.setText(userMessages[position].getmUserLogin());
}
@NonNull
@Override
public ChatHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_message, parent, false);
return new ChatHolder(view);
}
static class ChatHolder extends RecyclerView.ViewHolder {
@BindView(R.id.user_message)
TextView message;
@BindView(R.id.user_login)
TextView user;
private ChatHolder(View itemView) {
super(itemView);
ButterKnife.bind(itemView);
}
}
}
问题是,无论我如何尝试通过数组向 FirebaseRecyclerAdapter 发送选项(用户消息),它的计数始终为 0。可能问题出在自定义解析器下(我必须正确组合它),但我的调试器只是跳过了这部分代码:
public UserMessage parseSnapshot(@NonNull DataSnapshot snapshot) {
Log.d("snapshot length", String.valueOf(snapshot.getChildrenCount()));
return snapshot.getValue(UserMessage.class);
}
所以我什至无法检查我在这里做错了什么。我已经想了好几个小时了,但我真的不知道该如何处理。
//编辑1:
由于@Alex Malmo 的建议,我将数据库键更改为:
和UserMessage.class到:
public class UserMessage {
private String userLogin, userMessage, uid;
public UserMessage() {}
public UserMessage(String userLogin, String userMessage, String uid) {
this.userLogin = userLogin;
this.userMessage = userMessage;
this.uid = uid;
}
public String getUserLogin() { return userLogin; }
public String getUserMessage() { return userMessage; }
public String getUid() { return uid; }
}
看起来这个东西还在 FirebaseRecyclerOptions 创建中。我试过这两种方法:
FirebaseRecyclerOptions<UserMessage> options = new FirebaseRecyclerOptions.Builder<UserMessage>()
.setQuery(query,
UserMessage.class)
.build();
和
FirebaseRecyclerOptions<UserMessage> options = new FirebaseRecyclerOptions.Builder<UserMessage>()
.setQuery(query,
new SnapshotParser<UserMessage>() {
@NonNull
@Override
public UserMessage parseSnapshot(@NonNull DataSnapshot snapshot) {
return snapshot.getValue(UserMessage.class);
}
})
.build();
在这两种情况下 - setQuery 方法中的第二个参数(解析部分)似乎被忽略了(编译器只是跳过该部分 - 它得到正确的查询,并直接进入 .build()),这似乎是一个整体适配器中的空数据有问题。
您的代码中的问题是您在字段中使用了错误的 getter。在您的模型中 class 以小写字母开头的字段。当您使用名为 mUserLogin
的字段时,Firebase 正在查找名为 getMUserLogin()
而不是 getmUserLogin()
的 getter。看到大写字母 M
与小写字母 m
了吗?这可能是您一无所获的最可能原因。你的模型 class 应该是这样的:
public class UserMessage {
private String userLogin, userMessage, uid;
public UserMessage() {}
public UserMessage(String userLogin, String userMessage, String uid) {
this.userLogin = userLogin;
this.userMessage = userMessage;
this.uid = uid;
}
public String getUserLogin() { return userLogin; }
public String getUserMessage() { return userMessage; }
public String getUid() { return uid; }
}
要在您的数据库中获得正确的数据,只需删除 旧数据并添加 新数据。您的代码现在应该可以工作了。
你也可以看看Java Naming Conventions。
好的,我终于解决了。问题是,我完全误解了 FirebaseRecyclerOptions 函数。我完全确定它在其中传递数据,整个事情是我试图获取该数据,而不让整个方法完成它的工作。
所以我更改了适配器结构:
class ChatMessagesAdapter extends FirebaseRecyclerAdapter<UserMessage, ChatMessagesAdapter.ChatHolder> {
private UserMessage[] userMessages;
/**
* Initialize a {@link RecyclerView.Adapter} that listens to a Firebase query. See
* {@link FirebaseRecyclerOptions} for configuration options.
*
* @param options
*/
public ChatMessagesAdapter(@NonNull FirebaseRecyclerOptions<UserMessage> options) {
super(options);
userMessages = (UserMessage[]) options.getSnapshots().toArray();
}
@Override
protected void onBindViewHolder(@NonNull ChatHolder holder, int position, @NonNull UserMessage model) {
holder.message.setText(userMessages[position].getmUserMessage());
holder.user.setText(userMessages[position].getmUserLogin());
}
@NonNull
@Override
public ChatHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_message, parent, false);
return new ChatHolder(view);
}
static class ChatHolder extends RecyclerView.ViewHolder {
@BindView(R.id.user_message)
TextView message;
@BindView(R.id.user_login)
TextView user;
private ChatHolder(View itemView) {
super(itemView);
ButterKnife.bind(itemView);
}
}
收件人:
class ChatMessagesAdapter extends FirebaseRecyclerAdapter<UserMessage, ChatMessagesAdapter.ChatHolder> {
private ArrayList<UserMessage> messagesList = new ArrayList<>();
/**
* Initialize a {@link RecyclerView.Adapter} that listens to a Firebase query. See
* {@link FirebaseRecyclerOptions} for configuration options.
*
* @param options
*/
ChatMessagesAdapter(@NonNull FirebaseRecyclerOptions<UserMessage> options) {
super(options); }
@Override
protected void onBindViewHolder(@NonNull ChatHolder holder, int position, @NonNull UserMessage model) {
messagesList.add(model);
holder.message.setText(messagesList.get(position).getUserMessage());
holder.user.setText(messagesList.get(position).getUserLogin());
}
@NonNull
@Override
public ChatHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_message, parent, false);
return new ChatHolder(this,view);
}
static class ChatHolder extends RecyclerView.ViewHolder {
@BindView(R.id.user_message)
TextView message;
@BindView(R.id.user_login)
TextView user;
private ChatHolder(ChatMessagesAdapter chatMessagesAdapter, View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
因此,如果您对整个 FirebaseUI 有任何疑问,我认为上面的例子很合适。
感谢@Alex Malmo 和@Yupi 的建议!
因此,我正在使用 Firebase UI 从数据库中获取数据。
它看起来像这样:
我想遍历 "messages" 以获取每个 child,并在我的应用程序中将其显示为消息。这就是我的 UserMessage class 的样子:
public class UserMessage {
private String mUserLogin;
private String mUserMessage;
private String mUID;
UserMessage(String userLogin, String userMessage, String uid) {
mUserLogin = userLogin;
mUserMessage = userMessage;
mUID = uid;
}
public String getmUserLogin() {
return mUserLogin;
}
public void setmUserLogin(String mUserLogin) {
this.mUserLogin = mUserLogin;
}
public String getmUserMessage() {
return mUserMessage;
}
public String getmUID() {
return mUID;
}
public void setmUID(String mUID) {
this.mUID = mUID;
}
public void setmUserMessage(String mUserMessage) {
this.mUserMessage = mUserMessage;
}
}
我想通过 FirebaseRecyclerOptions 获取它:
FirebaseRecyclerOptions<UserMessage> options =
new FirebaseRecyclerOptions.Builder<UserMessage>()
.setQuery(firebaseDatabaseModel.getQuery(), new SnapshotParser<UserMessage>() {
@NonNull
@Override
public UserMessage parseSnapshot(@NonNull DataSnapshot snapshot) {
Log.d("snapshot length", String.valueOf(snapshot.getChildrenCount()));
return snapshot.getValue(UserMessage.class);
}
})
.build();
这是我的 firebaseDatabaseModel.getQuery() 方法的样子:
public Query getQuery() {
DatabaseReference messageReference = database.child("messages");
return messageReference.limitToLast(50);
}
这就是我想在我的 FirebaseRecyclerAdapter 中设置数据的方式
class ChatMessagesAdapter extends FirebaseRecyclerAdapter<UserMessage, ChatMessagesAdapter.ChatHolder> {
private UserMessage[] userMessages;
/**
* Initialize a {@link RecyclerView.Adapter} that listens to a Firebase query. See
* {@link FirebaseRecyclerOptions} for configuration options.
*
* @param options
*/
public ChatMessagesAdapter(@NonNull FirebaseRecyclerOptions<UserMessage> options) {
super(options);
userMessages = (UserMessage[]) options.getSnapshots().toArray();
}
@Override
protected void onBindViewHolder(@NonNull ChatHolder holder, int position, @NonNull UserMessage model) {
holder.message.setText(userMessages[position].getmUserMessage());
holder.user.setText(userMessages[position].getmUserLogin());
}
@NonNull
@Override
public ChatHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_message, parent, false);
return new ChatHolder(view);
}
static class ChatHolder extends RecyclerView.ViewHolder {
@BindView(R.id.user_message)
TextView message;
@BindView(R.id.user_login)
TextView user;
private ChatHolder(View itemView) {
super(itemView);
ButterKnife.bind(itemView);
}
}
}
问题是,无论我如何尝试通过数组向 FirebaseRecyclerAdapter 发送选项(用户消息),它的计数始终为 0。可能问题出在自定义解析器下(我必须正确组合它),但我的调试器只是跳过了这部分代码:
public UserMessage parseSnapshot(@NonNull DataSnapshot snapshot) {
Log.d("snapshot length", String.valueOf(snapshot.getChildrenCount()));
return snapshot.getValue(UserMessage.class);
}
所以我什至无法检查我在这里做错了什么。我已经想了好几个小时了,但我真的不知道该如何处理。
//编辑1:
由于@Alex Malmo 的建议,我将数据库键更改为:
和UserMessage.class到:
public class UserMessage {
private String userLogin, userMessage, uid;
public UserMessage() {}
public UserMessage(String userLogin, String userMessage, String uid) {
this.userLogin = userLogin;
this.userMessage = userMessage;
this.uid = uid;
}
public String getUserLogin() { return userLogin; }
public String getUserMessage() { return userMessage; }
public String getUid() { return uid; }
}
看起来这个东西还在 FirebaseRecyclerOptions 创建中。我试过这两种方法:
FirebaseRecyclerOptions<UserMessage> options = new FirebaseRecyclerOptions.Builder<UserMessage>()
.setQuery(query,
UserMessage.class)
.build();
和
FirebaseRecyclerOptions<UserMessage> options = new FirebaseRecyclerOptions.Builder<UserMessage>()
.setQuery(query,
new SnapshotParser<UserMessage>() {
@NonNull
@Override
public UserMessage parseSnapshot(@NonNull DataSnapshot snapshot) {
return snapshot.getValue(UserMessage.class);
}
})
.build();
在这两种情况下 - setQuery 方法中的第二个参数(解析部分)似乎被忽略了(编译器只是跳过该部分 - 它得到正确的查询,并直接进入 .build()),这似乎是一个整体适配器中的空数据有问题。
您的代码中的问题是您在字段中使用了错误的 getter。在您的模型中 class 以小写字母开头的字段。当您使用名为 mUserLogin
的字段时,Firebase 正在查找名为 getMUserLogin()
而不是 getmUserLogin()
的 getter。看到大写字母 M
与小写字母 m
了吗?这可能是您一无所获的最可能原因。你的模型 class 应该是这样的:
public class UserMessage {
private String userLogin, userMessage, uid;
public UserMessage() {}
public UserMessage(String userLogin, String userMessage, String uid) {
this.userLogin = userLogin;
this.userMessage = userMessage;
this.uid = uid;
}
public String getUserLogin() { return userLogin; }
public String getUserMessage() { return userMessage; }
public String getUid() { return uid; }
}
要在您的数据库中获得正确的数据,只需删除 旧数据并添加 新数据。您的代码现在应该可以工作了。
你也可以看看Java Naming Conventions。
好的,我终于解决了。问题是,我完全误解了 FirebaseRecyclerOptions 函数。我完全确定它在其中传递数据,整个事情是我试图获取该数据,而不让整个方法完成它的工作。
所以我更改了适配器结构:
class ChatMessagesAdapter extends FirebaseRecyclerAdapter<UserMessage, ChatMessagesAdapter.ChatHolder> {
private UserMessage[] userMessages;
/**
* Initialize a {@link RecyclerView.Adapter} that listens to a Firebase query. See
* {@link FirebaseRecyclerOptions} for configuration options.
*
* @param options
*/
public ChatMessagesAdapter(@NonNull FirebaseRecyclerOptions<UserMessage> options) {
super(options);
userMessages = (UserMessage[]) options.getSnapshots().toArray();
}
@Override
protected void onBindViewHolder(@NonNull ChatHolder holder, int position, @NonNull UserMessage model) {
holder.message.setText(userMessages[position].getmUserMessage());
holder.user.setText(userMessages[position].getmUserLogin());
}
@NonNull
@Override
public ChatHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_message, parent, false);
return new ChatHolder(view);
}
static class ChatHolder extends RecyclerView.ViewHolder {
@BindView(R.id.user_message)
TextView message;
@BindView(R.id.user_login)
TextView user;
private ChatHolder(View itemView) {
super(itemView);
ButterKnife.bind(itemView);
}
}
收件人:
class ChatMessagesAdapter extends FirebaseRecyclerAdapter<UserMessage, ChatMessagesAdapter.ChatHolder> {
private ArrayList<UserMessage> messagesList = new ArrayList<>();
/**
* Initialize a {@link RecyclerView.Adapter} that listens to a Firebase query. See
* {@link FirebaseRecyclerOptions} for configuration options.
*
* @param options
*/
ChatMessagesAdapter(@NonNull FirebaseRecyclerOptions<UserMessage> options) {
super(options); }
@Override
protected void onBindViewHolder(@NonNull ChatHolder holder, int position, @NonNull UserMessage model) {
messagesList.add(model);
holder.message.setText(messagesList.get(position).getUserMessage());
holder.user.setText(messagesList.get(position).getUserLogin());
}
@NonNull
@Override
public ChatHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_message, parent, false);
return new ChatHolder(this,view);
}
static class ChatHolder extends RecyclerView.ViewHolder {
@BindView(R.id.user_message)
TextView message;
@BindView(R.id.user_login)
TextView user;
private ChatHolder(ChatMessagesAdapter chatMessagesAdapter, View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
因此,如果您对整个 FirebaseUI 有任何疑问,我认为上面的例子很合适。
感谢@Alex Malmo 和@Yupi 的建议!