英文:
for loop not running inside single value event listener
问题
我正在尝试实现一个搜索功能,在点击搜索结果后,我会在一个片段中显示用户的详细信息。问题出现在 init()
函数中,onDataChange()
函数内部的 foreach 循环不会执行。
private User mUser;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_view_profile, container, false);
try{
mUser = getUserFromBundle();
init();
}catch (NullPointerException e){
Log.e(TAG, "onCreateView: NullPointerException: " + e.getMessage() );
setupFirebaseAuth();
return view;
}
}
private void init(){
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.child(getString(R.string.db_user_account_settings)).orderByChild(getString(R.string.field_user_id)).equalTo(mUser.getUserid());
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
UserSettings settings = new UserSettings();
settings.setUser(mUser);
settings.setSettings(singleSnapshot.getValue(UserAccountSettings.class));
setProfileWidgets(settings);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
private User getUserFromBundle(){
Bundle bundle = this.getArguments();
if(bundle != null){
return bundle.getParcelable(getString(R.string.intent_user));
}else{
return null;
}
}
strings.xml
<resources>
<string name="field_user_id">user_id</string>
<string name="intent_user">intent_user</string>
<string name="db_user_account_settings">user_account_settings</string>
</resources>
我不知道为什么这不起作用。
从评论中:
1),2)我已经添加了你可以参考的
strings.xml
代码 3)屏幕截图中的蓝色箭头显示了返回的用户ID(这正是我想要的) 4)红色部分是我正在查询的内容 5)是的,我对 JSON 和 Firebase 有点陌生。
英文:
I'm trying to implement a search feature where, upon clicking on the search result, I display the user's details in a fragment. The problem is in the init()
function where the foreach loop inside the onDataChange()
funcion doesn't execute.
private User mUser;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_view_profile, container, false);
try{
mUser = getUserFromBundle();
init();
}catch (NullPointerException e){
Log.e(TAG, "onCreateView: NullPointerException: " + e.getMessage() );
setupFirebaseAuth();
return view;
}
private void init(){
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.child(getString(R.string.db_user_account_settings)).orderByChild(getString(R.string.field_user_id)).equalTo(mUser.getUserid());
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
UserSettings settings = new UserSettings();
settings.setUser(mUser);
settings.setSettings(singleSnapshot.getValue(UserAccountSettings.class));
setProfileWidgets(settings);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
private User getUserFromBundle(){
Bundle bundle = this.getArguments();
if(bundle != null){
return bundle.getParcelable(getString(R.string.intent_user));
}else{
return null;
}
}
strings.xml
<resources>
<string name="field_user_id">user_id</string>
<string name="intent_user">intent_user</string>
<string name="db_user_account_settings">user_account_settings</string>
</resources
I have no idea why this isn't working.
From comment:
> 1), 2) I've added the strings.xml code you can refer to 3) The blue arrow in the screenshot shows the userid that is returned (which is exactly what I want) 4) The red portion is what I'm querying 5) Yes. I'm a bit new with JSON and firebase,
答案1
得分: 1
你的代码执行以下操作:
reference.child("user_account_settings").orderByChild("user_id").equalTo(mUser.getUserid())
这将:
- 获取
user_account_settings
下的所有子节点。 - 根据它们的
user_id
属性的值进行排序。 - 仅选择该值存在且等于UID的节点。
由于你展示的 JSON 中没有显示user_id
属性,所以没有结果。
如果你要查找的值作为节点的键,你可以直接使用child(...)
来查找该节点。并且由于具有给定键的节点只能有一个子节点,这意味着你在onDataChange
方法中不再需要对getChildren()
进行循环。
所以类似这样的代码:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.child(getString(R.string.db_user_account_settings)).child(mUser.getUserid());
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserSettings settings = new UserSettings();
settings.setUser(mUser);
settings.setSettings(singleSnapshot.getValue(UserAccountSettings.class));
setProfileWidgets(settings);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
英文:
Your code does:
reference.child(getString(R.string.db_user_account_settings)).orderByChild(getString(R.string.field_user_id)).equalTo(mUser.getUserid())
Which translates to:
reference.child("user_account_settings").orderByChild("user_id").equalTo(mUser.getUserid())
So it:
- Takes all child nodes under
user_account_settings
. - Orders them on the value of their
user_id
property. - Selects only the nodes where that value exists and is equal to the UID.
Since the JSON you showed doesn't show a user_id
property, there are no results.
If you have the value you are looking for as the key of a node, you can just use child(...)
to look that node up. And since there can only be one child node with a given key, that means you no longer need the loop over getChildren()
in the onDataChange
method.
So something like:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.child(getString(R.string.db_user_account_settings)).child(mUser.getUserid());
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserSettings settings = new UserSettings();
settings.setUser(mUser);
settings.setSettings(singleSnapshot.getValue(UserAccountSettings.class));
setProfileWidgets(settings);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论