0

Am trying to build and return ArrayList from firebase DataSnapshot.

My database structure

enter image description here

I have this ListItem Class.

public class ListItem {
    private String title;
    private String message;
    private String image;
    private String type;
    private String userid;

    public String getTitle() {return title;}
    public String getMessage() {return message;}
    public String getImage() {return image;}
    public String getType() {return type;}
    public String getUserid() {return userid;}
    public void setTitle(String title) {this.title = title;}
    public void setMessage(String message) {this.message = message;}
    public void setImage(String image) {this.image = image; }
    public void setType(String type) {this.type = type; }
    public void setUserid(String userid) {this.userid = userid;}
}

I have this loadNotificationDatabase method for testing which is working fine.

private ArrayList loadNotificationDatabase() {
    ArrayList<ListItem> results = new ArrayList<>();
    ListItem user1 = new ListItem();
    user1.setTitle("Suresh Dasari");
    user1.setMessage("Team Leader");
    user1.setUserid("Hyderabad");
    results.add(user1);
    ListItem user2 = new ListItem();
    user2.setTitle("Rohini Alavala");
    user2.setMessage("Agricultural Officer");
    user2.setUserid("Guntur");
    results.add(user2);
    ListItem user3 = new ListItem();
    user3.setTitle("Trishika Dasari");
    user3.setMessage("Charted Accountant");
    user3.setUserid("Guntur");
    results.add(user3);
    return results;
}

Now I tried to load data from firebase database and return array list, but it doesn't return anything its always empty array and no error. I know that am not getting the code right, please can anyone assist me?

   public ArrayList loadNotificationDatabase() {
        String userSessionId = "QvdfKO9ek4qlPZJA";
        ArrayList<ListItem> list = new ArrayList<>();
        ValueEventListener valueEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for(DataSnapshot ds : dataSnapshot.getChildren()) {
                    ListItem users = new ListItem();
                    users.setTitle(ds.child("title").getValue(String.class));
                    users.setMessage(ds.child("message").getValue(String.class));
                    users.setUserid(ds.child("user_id").getValue(String.class));
                    list.add(users);

                    String message = ds.child("message").getValue(String.class);
                    String title = ds.child("title").getValue(String.class);
                    String type = ds.child("type").getValue(String.class);
                    String image = ds.child("image").getValue(String.class);
                    String user_id = ds.child("user_id").getValue(String.class);
                    Log.d("loadNotification", title + " / " + message  + " / " + type + " / " + image + " / " + user_id);
                }
                Log.e("loadNotification", list.toString());
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.e("DatabaseError", databaseError.getMessage());
            }
        };
        notificationDatabase.child(userSessionId).addListenerForSingleValueEvent(valueEventListener);
        return list;
    }

 ArrayList userList = loadNotificationDatabase();
 Log.e("userLists", userList.toString());
Edric
  • 24,639
  • 13
  • 81
  • 91
Peter
  • 1,860
  • 2
  • 18
  • 47
  • Please check the duplicate to see why do you have this behavior and how can you solve this using a custom callback. – Alex Mamo Dec 17 '19 at 11:10
  • the callback is asynchronous. you can check the list size in `onDataChange`. you need to modify the logic accordingly. if you query is right the list is populated however it does take some time as it is asynchronous. but you return list immediately which may not be populated yet. – Raghunandan Dec 17 '19 at 11:12
  • @AlexMamo is not really same, I can get values, but what am trying to do is to return ArrayList of all data – Peter Dec 17 '19 at 11:14
  • @Raghunandan I updated my question, you can see my database structure. – Peter Dec 17 '19 at 11:17
  • @Peter There is no way you can return a list as a result of a method. – Alex Mamo Dec 17 '19 at 11:17
  • You can't return list form onDataChange method because it's void type for that you need to create interface callback and call interface in onDataChange methond like: interfacecallBack.addList(list); and add argument this interface in ArrayList loadNotificationDatabase(MyCallback interfacecallBack) – Abhishek Hirapara Dec 17 '19 at 11:18
  • @Peter still the same its asynchronous so you need to wait for the list to be populated. something like interface to notify if list is populated successfully then go ahead with the rest of the logic as suggested by abhisek. – Raghunandan Dec 17 '19 at 11:19
  • @AbhishekHirapara I have just implemented the call back following this example https://stackoverflow.com/a/47853774/8235983 but still don't know how I can return arrayList from it – Peter Dec 17 '19 at 11:44
  • Technically, you are returning the object reference to list. But because populating the list is an asynchronous operation (and will take time to complete) by the time the code `userList.toString()` is evaluated, your list would still be empty. If after that line you added a delay, say 30s using `Thread.sleep(30000)` and then called that line again, it **may** now have data. – samthecodingman Dec 17 '19 at 11:55
  • You could wrap the ArrayList in a [`Future`](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html) and then wait for it to be filled using `someFuture.get()`, but this would block your application's main thread making your app seem like it has broken (can't scroll, use back navigation, etc) leading to a poor user-experience. – samthecodingman Dec 17 '19 at 12:04
  • @samthecodingman I was able to get it working, but it has a warning `uses unchecked or unsafe operations` which I have tried but unable to resolve it. – Peter Dec 17 '19 at 13:57
  • You shouldn't be trying to persist with "returning the list" as you are above. The comments here, the linked question and that warning all cover why you shouldn't do this and should instead rethink how you are going to achieve the task at hand. – samthecodingman Dec 17 '19 at 14:29
  • @Peter Create interface like: public interface MyCallback { void onCallback(List value); } as I mention previously in data change : interfacecallBack.addList(list) and call your arraylist method like : loadNotificationDatabase(new MyCallback) so you can get call back in implemented method while calling loadNotificationDatabase method. – Abhishek Hirapara Dec 18 '19 at 11:27

0 Answers0