4

I am using SingleValueEventListener to get some data from Firebase Database. Having acquired the data, I need to get another Firebase database reference using that data. Later, I need to use the second/new Firebase database ref inside different method.

When I use this second reference, I am getting null object reference exception. Here is the code. It is from onCreate():

 mCurrentUserDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String university = dataSnapshot.child("university").getValue().toString();
            String groupid = dataSnapshot.child("groupid").getValue().toString();
            //Having acquired university and group ID, now we can get reference to group members list
            mMembersDatabase = FirebaseDatabase.getInstance().getReference().child("Universities").child(university).child("Groups").child(groupid).child("Members");

And, I need to use this mMembersDatabase again in onStart() method. How can i do this? Please dont suggest to get the ref inside onStart(). I need to know how can i pass the ref from one method to another method.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Azizjon Kholmatov
  • 1,136
  • 1
  • 13
  • 26
  • if there are many universities then you will need to do it inside a foreach loop. show a screenshot of your firebase structure – Amir Dora. Jan 09 '18 at 07:19

2 Answers2

1

First of all you need to create data class:

public class UniversityData {

    String university;
    String groupId;

    public String getUniversity() {
        return university;
    }

    public void setUniversity(String university) {
        this.university = university;
    }

    public String getGroupId() {
        return groupId;
    }

    public void setGroupId(String groupid) {
        this.groupId = groupid;
    }
}

Using this class you can parse all result from firebase to your activity. Then you need to create your custom listener interface which listens if new data was received:

public interface DataListener<DATA> {
    void onDataReceived(DATA data);
}

Then use data class in your firebase data receiver:

    public void getUniversityData(final DataListener<UniversityData> listener) {
        final UniversityData[] dataArray = new UniversityData[1];
        DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
        mDatabase.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    if (snapshot!=null) {
                        //String university = dataSnapshot.child("university").getValue().toString();
                        //String groupid = dataSnapshot.child("groupid").getValue().toString();
                        dataArray[0] = snapshot.getValue(UniversityData.class);
                    }
                }
                listener.onDataReceived(dataArray[0]);
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {}
        });
    }

Then in your activity implement created data listener:

public class MainPage extends AppCompatActivity implements DataListener<UniversityData> {

    @Override
    public void onDataReceived(UniveristyData data) {
        String university = data.getUniversity();
        String groupid = data.getGroupid();
    }
}

And that's all. Now you can use your received data in your activity from created listener.

To call method in activity which implements listener use getUniversityData(this);

Hope it helps.

Dumbo
  • 1,630
  • 18
  • 33
1

You are getting null because onDataChange() method is called asynccrounus. It means that is called even before you getting the data from the database. To use the value of your mMembersDatabase outside onDataChange() method you need to create your own callback.

To achieve this, first you need to create an interface like this:

public interface MyCallback {
    void onCallback(DatabaseReference databaseReference);
}

Then you need to create a method that is actually getting the data from the database. This method should look like this:

public void readData(MyCallback myCallback) {
    mCurrentUserDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String university = dataSnapshot.child("university").getValue().toString();
            String groupid = dataSnapshot.child("groupid").getValue().toString();
            //Having acquired university and group ID, now we can get reference to group members list
            mMembersDatabase = FirebaseDatabase.getInstance().getReference().child("Universities").child(university).child("Groups").child(groupid).child("Members");
            myCallback.onCallback(mMembersDatabase);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });
}

In the end, in your onStart() method, just simply call readData() method and pass MyCallback as an argument like this:

readData(new MyCallback() {
    @Override
    public void onCallback(DatabaseReference databaseReference) {
        //use the value of your databaseReference
    }
});

This is the only way in which you can use that value outside onDataChange() method. For more information please see my answer from this post.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thank you! It is working great. I have also visited the link you provided. Great explanation! – Azizjon Kholmatov Jan 09 '18 at 14:08
  • I also wanted to ask, what if, I want to pass this mMembersDatabase reference as a parameter to FirebaseRecyclerAdapter? How can I achieve this? – Azizjon Kholmatov Jan 09 '18 at 14:09
  • You're welcome! You need to use it in the same way. When you are calling the `readData()` method, inside the `onCallback()` method, pass the `databaseReference` object to the `FirebaseRecyclerAdapter`. – Alex Mamo Jan 09 '18 at 14:13
  • I am afraid i did not get what you meant. Could you explain once again? – Azizjon Kholmatov Jan 09 '18 at 14:38
  • `databaseReference` is available inside the `onCallback()` method. Now, take this `databaseReference` object in pass it to the `FirebaseRecyclerAdapter` constructor. That's it. – Alex Mamo Jan 09 '18 at 14:42
  • Do you mean that I have to create the `FirebaseRecyclerAdapter` inside the `onCallback()`? I tried this but it is not working. – Azizjon Kholmatov Jan 09 '18 at 15:03
  • I cannot give you a solution having only the code above which you provided for the initial question. So, this is basically another question. So i suggest you post another fresh question, so me and other users can help you. Don't forget to add a [mcv](https://stackoverflow.com/help/mcve). – Alex Mamo Jan 09 '18 at 15:07