Android-Firebase-获取儿童数据的孩子 [英] Android - Firebase - Getting Child of Child Data
问题描述
目标
要通过中的数据树获取当前用户的数据,例如姓名,地址,邻居 Firebase数据库
To prompt the data of the current user such as name, address, neighbourhood by acquiring them through the Data Tree within Firebase Database
数据树的图片
目标
通过管理员帐户添加了数据树中的伦敦"和华盛顿"子级,这意味着它们不是固定的,并且可以添加其他子级,例如纽约".
The "London" and "Washington" child within the Data Tree are added in by the Admin account, which means that they are not fixed and that an additional child such as "New York" can be added.
这意味着新编辑的数据树将在用户"下,而伦敦",华盛顿"和纽约"下
Which would mean that the newly edited Data Tree will have under "Users", there will be "London", "Washington", and "New York"
其他孩子,例如下面显示的孩子,都是固定的.
The other childs, such as those shown below are fixed.
-
后卫
Guards
- 名称
- 社区
警察
- 地址
- 名称
- 社区
居民
-
地址
address
图片
名称
社区
位置
状态
问题
尝试提示登录的当前用户的数据后,我收到"java.lang.NullPointerException".
I receive a "java.lang.NullPointerException" after attempting to prompt the data of the current user who is logged in.
错误显示在代码String stgUserHomeName = dataSnapshot.child("Users").getValue().toString();
处.
我以前可以获取所需的数据,例如姓名",地址"等,但是当我添加非固定父母(例如伦敦")时遇到问题时"和华盛顿".
I was able to acquire my desired data such as "name", "address" and etc. before but when I had a problem when I added in a Not-Fixed parent such as "London" and "Washington".
SettingsActivity类
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import com.squareup.picasso.Callback;
import com.squareup.picasso.NetworkPolicy;
import com.squareup.picasso.Picasso;
import java.io.File;
public class SettingsActivity extends AppCompatActivity {
private DatabaseReference jSettingsDatabase;
private FirebaseUser jFirebaseCurrentUser;
private Toolbar jSettingsToolbar;
private ImageView jSettingsImageView;
private TextView jSettingsDisplayName;
private TextView jSettingsStatus;
private TextView jSettingsAddress;
private TextView jSettingsHomeName;
private Button jSettingsDetailsBtn;
private Button jSettingsImageBtn;
private static final int jSettingsGallerySelect = 1;
private StorageReference jSettingsStorageReference;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
jSettingsStorageReference = FirebaseStorage.getInstance().getReference();
jFirebaseCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
String settingsUserID = jFirebaseCurrentUser.getUid();
jSettingsDatabase = FirebaseDatabase.getInstance().getReference().child("Resident").child(settingsUserID);
jSettingsDatabase.keepSynced(true);
jSettingsImageView = (ImageView) findViewById(R.id.settingUserImg);
jSettingsToolbar = (Toolbar) findViewById(R.id.settingsToolBar);
setSupportActionBar(jSettingsToolbar);
getSupportActionBar().setTitle("Settings");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
jSettingsDisplayName = (TextView) findViewById(R.id.settingUserNameTxt);
jSettingsStatus = (TextView) findViewById(R.id.settingUserStatusTxt);
jSettingsAddress = (TextView) findViewById(R.id.settingUserAddressTxt);
jSettingsHomeName = (TextView) findViewById(R.id.settingsUserHomeTxt);
jSettingsDetailsBtn = (Button) findViewById(R.id.settingChangeDetailsBtn);
jSettingsImageBtn = (Button) findViewById(R.id.settingChangeImageBtn);
jSettingsDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String stgUserHomeName = dataSnapshot.child("Users").getValue().toString();
String stgUserName = dataSnapshot.child("Users").child(stgUserHomeName).child("name").getValue().toString();
String stgUserStatus = dataSnapshot.child("Users").child(stgUserHomeName).child("status").getValue().toString();
String stgUserHomeAddress = dataSnapshot.child("Users").child(stgUserHomeName).child("address").getValue().toString();
final String stgUserImage = dataSnapshot.child("Users").child(stgUserHomeName).child("image").getValue().toString();
jSettingsDisplayName.setText(stgUserName);
jSettingsStatus.setText(stgUserStatus);
jSettingsAddress.setText(stgUserHomeAddress);
if(!stgUserImage.equals("default")){
Picasso.with(SettingsActivity.this).load(stgUserImage).networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.avataricon).into(jSettingsImageView, new Callback() {
@Override
public void onSuccess() {
}
@Override
public void onError() {
Picasso.with(SettingsActivity.this).load(stgUserImage).placeholder(R.drawable.avataricon).into(jSettingsImageView);
}
});
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
jSettingsDetailsBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String stgUserStatusValue = jSettingsStatus.getText().toString();
String stgUserAddressValue = jSettingsAddress.getText().toString();
String stgUserNameValue = jSettingsDisplayName.getText().toString();
Intent intentDetails = new Intent(SettingsActivity.this, DetailsActivity.class);
intentDetails.putExtra("stgUserNameValue" , stgUserNameValue);
intentDetails.putExtra("stgUserStatusValue", stgUserStatusValue);
intentDetails.putExtra("stgUserAddressValue", stgUserAddressValue);
startActivity(intentDetails);
}
});
jSettingsImageBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intentGallery = new Intent();
intentGallery.setType("image/*");
intentGallery.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intentGallery, "SELECT IMAGE"), jSettingsGallerySelect);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == jSettingsGallerySelect && resultCode == RESULT_OK){
Uri imageUri = data.getData();
String currentUserID = jFirebaseCurrentUser.getUid();
StorageReference imageFilePath = jSettingsStorageReference.child("profileImages").child(currentUserID+".jpg");
imageFilePath.putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>(){
@Override
public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
@SuppressWarnings("VisibleForTests")
String downloadImageUrl = task.getResult().getDownloadUrl().toString();
jSettingsDatabase.child("image").setValue(downloadImageUrl).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if(task.isSuccessful()){
Toast.makeText(SettingsActivity.this, "Upload Successful", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(SettingsActivity.this, "Upload Failed", Toast.LENGTH_SHORT).show();
}
}
});
}
});
}
}
}
代码说明
jSettingsHomeName
和stgUserHomeName
分别是伦敦",华盛顿"等.
The jSettingsHomeName
and stgUserHomeName
are meant to be the "London", "Washington", and etc.
几乎相似的问题的解决方案
在链接中:如何获取,它显示了程序员如何获取孩子的孩子,但是我之所以无法遵循的原因是因为我的伦敦"和华盛顿"孩子层不是固定的
In the link: How to get child of child value from firebase in android? , it shows how a programmer can get the child of a child but the reason as to why I am unable to follow the is because my "London" and "Washington" child tier isn't fixed
更新:Ewald B提供的试用解决方案.
jSettingsDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot node : dataSnapshot.getChildren()) {
String stgUserHomeName = node.getKey();
String stgUserName = node.child("Resident").child(settingsUserID).child("name").getValue().toString();
String stgUserStatus = node.child("Resident").child(settingsUserID).child("status").getValue().toString();
String stgUserHomeAddress = node.child("Resident").child(settingsUserID).child("address").getValue().toString();
final String stgUserImage = node.child("Resident").child(settingsUserID).child("image").getValue().toString();
jSettingsHomeName.setText(stgUserHomeName);
jSettingsDisplayName.setText(stgUserName);
jSettingsStatus.setText(stgUserStatus);
jSettingsAddress.setText(stgUserHomeAddress);
if(!stgUserImage.equals("default")){
Picasso.with(SettingsActivity.this).load(stgUserImage).networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.avataricon).into(jSettingsImageView, new Callback() {
@Override
public void onSuccess() {
}
@Override
public void onError() {
Picasso.with(SettingsActivity.this).load(stgUserImage).placeholder(R.drawable.avataricon).into(jSettingsImageView);
}
});
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
错误
com.example.task.app.SettingsActivity $ 1.onDataChange(SettingsActivity.java:91)上的java.lang.NullPointerException
java.lang.NullPointerException at com.example.task.app.SettingsActivity$1.onDataChange(SettingsActivity.java:91)
第91行指向String stgUserName = node.child("Resident").child(settingsUserID).child("name").getValue().toString();
推荐答案
根据数据模型并查看此语句
According to the data model and looking at this statement
jSettingsDatabase = FirebaseDatabase.getInstance().getReference().child("Resident").child(settingsUserID);
/Resident/userId
下没有节点User
.查询需要从数据库的根目录开始,我假设该根目录为User
.
there's no node User
underneath /Resident/userId
. The query needs to start at the database's root which, I assume, is User
.
为了获得London, Washington, etc.
,您需要将代码修改为:
In order to get London, Washington, etc.
you need to adapt the code to:
jSettingsDatabase = FirebaseDatabase.getInstance().getReference().child("Users");
...
jSettingsDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot node : dataSnapshot.getChildren()) {
// you will get all cities
String stgUserHomeName = node.getKey();
if(!"Washington".equals(stgUserHomeName)) // or whatever city you need
continue;
// add some more conditional logic to cope with the distinct subtrees that don't have the same properties
// London's Resident has more properties than Washington --> exception is thrown then
// to get the resident's data
node.child("Resident").child(userId).child("address")...
node.child("Resident").child(userId).child("image")...
// or
node.child("Resident").child(userId).getValue(Resident.class);
...
}
....
}
});
您的树中没有此查询所需的用户ID.但是根据数据库的访问规则,可能有必要.显然,其他查询也需要进行调整.城市名称也不是值,而是键(必须唯一),因此调用DataSnapshot.getKey()
方法很重要.
There's no user ID in your tree that is needed for this query. But it might be necessary depending on the DB's access rules. Obviously the other queries need to be adapted as well. The city names are also not values but a key (must be unique) so what is important to call DataSnapshot.getKey()
method.
在您的情况下,将从用户向下的整个数据库中获取数据,并在客户端上丢弃所有不需要的城市.那是浪费资源.
In your case the whole database from the User downwards will be fetched and on the client all cities that are not needed will be thrown away. That's a waste of resources.
这篇关于Android-Firebase-获取儿童数据的孩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!