Android-Firebase-获取儿童数据的孩子 [英] Android - Firebase - Getting Child of Child Data

查看:47
本文介绍了Android-Firebase-获取儿童数据的孩子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标

要通过中的数据树获取当前用户的数据,例如姓名地址邻居 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();
                            }
                        }
                    });
                }
            });
        }
    }
}

代码说明

jSettingsHomeNamestgUserHomeName分别是伦敦",华盛顿"等.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆