Reputation: 151
I'm sorry if this may seem like a stupid question, but I haven't found any similar questions around so here goes.
I have a class DatabaseService for retrieving data(Animal) from the Firebase Realtime-Database. From a previous post I've learned that because these API calls are asynchronous, one should create an Interface in order to sync the retrieval of data ( the onDataChange() method )
My questions are:
Having created this class as a database service (hence the name), I want it to return a list of animals ( List ) for the Activity that containts this service, MyAnimalsActivity , in order to make a RecyclerView. Is there any way I can change the "void" in this Interface method to "List" to have something like
List<Animal> listAnimals = databaseService.readData();
or should this entire DatabaseService class rather be removed and add its' code in the MyAnimalsActivity itself, in order to add the Animals Objects inside a global list in the onDataChange() method?
DatabaseService:
public class DatabaseService {
private FirebaseDatabase firebaseDatabase;
private DatabaseReference firebaseRootRef;
private DatabaseReference animalsRef;
List<Animal> animalsList;
public DatabaseService() {
this.firebaseDatabase = FirebaseDatabase.getInstance();
this.firebaseRootRef = firebaseDatabase.getReference();
this.animalsRef = firebaseDatabase.getReference("animals");
animalsList = new ArrayList<>();
}
private interface FirebaseCallback {
void onCallback(List<Animal> list);
}
public void readItemsFromDatabase(final FirebaseCallback firebaseCallback) {
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
animalsList.clear();
//dataSnapshot.getChildren() ---> iterate through entire dataSnapshot Object, to get the items names
for(DataSnapshot ds : dataSnapshot.getChildren()) {
Animal animal;
animal = ds.getValue(Animal.class);
animalsList.add(animal);
}
firebaseCallback.onCallback(animalsList);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.d("DATABASE_TAG", databaseError.getMessage());
}
};
animalsRef.addValueEventListener(valueEventListener);
}
public void readData() {
readItemsFromDatabase(new FirebaseCallback() {
@Override
public void onCallback(List<Animal> list) {
Log.d("DATABASE_TAG", list.toString());
}
});
}
}
MyAnimalsActivity :
public class MyAnimalsActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerView.Adapter animalAdapter;
private List<Animal> listAnimals;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_animals);
DatabaseService databaseService = new DatabaseService();
databaseService.readData();
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true); //every item of the recyclerview has a fixed size;
recyclerView.setLayoutManager(new LinearLayoutManager(this));
listAnimals = new ArrayList<>();
//listAnimals = databaseService.readData(); ??
}
}
Upvotes: 0
Views: 355
Reputation: 13129
Writing a method that returns an asynchronous value that might be not there can cause NullPointers if you call it before it has the data.
To make this simple, since the method readItemsFromDatabase
is public, you can call it from your MyAnimalsActivity
and get your data from there.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_animals);
DatabaseService databaseService = new DatabaseService();
databaseService.readItemsFromDatabase(new DatabaseService.FirebaseCallback() {
@Override
public void onCallback(List<Animal> list) {
Log.d("DATABASE_TAG", list.toString());
}
});
...
I have isolated your issue with a project of mine and it's working; also, you can check the MVP pattern that will solve all these issues for you and your code will become cleaner.
Upvotes: 2