瞄准
通过内的数据树获取当前用户的姓名、地址、邻居等数据Firebase 数据库
数据 TreeMap 片
描述
数据树中的“伦敦”和“华盛顿”子级由管理员帐户添加,这意味着它们不是固定的,并且可以添加其他子级,例如“纽约”。
这意味着新编辑的数据树将在“用户”下包含“伦敦”、“华盛顿”和“纽约”
其他子项(如下所示)已修复。
守卫
- 姓名
- 社区
警察
- 地址
- 姓名
- 社区
居民
地址
图像
姓名
社区
位置
状态
问题
尝试提示当前登录用户的数据后,我收到“java.lang.NullPointerException”。
错误显示在代码 String stgUserHomeName = dataSnapshot.child("Users").getValue().toString();
处。
我之前能够获取我想要的数据,例如“姓名”,“地址”等,但是当我添加未修复父级(例如“伦敦”)时遇到问题”和“华盛顿”。
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
应该是“伦敦”、“华盛顿”等。
几乎类似问题的解决方案
在链接中:How to get child of child value from firebase in android? ,它展示了程序员如何获得 child 的 child ,但我无法遵循的原因是因为我的“伦敦”和“华盛顿” child 层未固定
更新:尝试 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
第91行指向String stgUserName = node.child("Resident").child(settingsUserID).child("name").getValue().toString();
最佳答案
根据数据模型,看这个说法
jSettingsDatabase = FirebaseDatabase.getInstance().getReference().child("Resident").child(settingsUserID);
/Resident/userId
下没有节点 User
。查询需要从数据库的根开始,我假设是User
。
为了获得伦敦、华盛顿等
,您需要将代码调整为:
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()
方法很重要。
在您的情况下,将从用户向下的整个数据库将被获取,并且在客户端上所有不需要的城市将被丢弃。这是资源的浪费。
关于java - Android - Firebase - 获取子数据的子数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46382925/