Reputation: 25
I am loading data from cloud firestore
into a custom recyclerview adapter. According to my log I get the data from firestore
just fine and inside of my get method the log shows my list size increasing. Outside of my get method mWorkoutList goes back to size 0. I cannot figure out why this is happening.
public class ViewWorkoutsActivity extends AppCompatActivity implements WorkoutAdapter.WorkoutAdapterOnClickHandler {
private final String TAG = this.getClass().getName();
private FirebaseFirestore db;
private String mUid;
private List<Set> mSetList;
private RecyclerView mRecyclerView;
private WorkoutAdapter mWorkoutAdapter;
private List<OtherWorkout> mWorkoutList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_workouts);
mWorkoutList = new ArrayList<>();
mUid = getIntent().getStringExtra("uid");
db = FirebaseFirestore.getInstance();
initDatabaseData();
mRecyclerView = findViewById(R.id.recycler_view);
LinearLayoutManager linearLayoutManager
= new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setHasFixedSize(true);
mWorkoutAdapter = new WorkoutAdapter(this);
mRecyclerView.setAdapter(mWorkoutAdapter);
Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());
mWorkoutAdapter.setWorkoutData(mWorkoutList);
}
@Override
public void onClick(OtherWorkout workout) {
}
public void initDatabaseData(){
CollectionReference collectionReference2 = db.collection("users").document(mUid).collection("workouts");
collectionReference2.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()){
for (QueryDocumentSnapshot document : task.getResult()){
OtherWorkout workout = document.toObject(OtherWorkout.class);
mWorkoutList.add(workout);
Log.i("LOG", "workout list size: " + mWorkoutList.size());
}
}
}
});
}
}
Upvotes: 0
Views: 224
Reputation: 3691
addOnCompleteListener
provides a way to add asynchronous task listener.
When you call initDatabaseData()
, you start the task and define a listener. But there is no guarantee that this task is completed when returning from initDatabaseData
.
That's why, once you print mWorkoutList
size in the onCreate
method, the value can be different from the one printed in the listener.
To avoid that, you can change the way your program works either by changing the async mechanism to a sync one, or by the part using the data to the listener onComplete
method
Upvotes: 0
Reputation: 346
Hi Allen you are calling initDatabaseData(); in oncreate() method which is making Network Request and fetching data. So it takes roughly around 2-3 seconds to fetch the data. But In that 2-3 seconds your code below initDatabaseData() getting called
LinearLayoutManager linearLayoutManager
= new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setHasFixedSize(true);
mWorkoutAdapter = new WorkoutAdapter(this);
mRecyclerView.setAdapter(mWorkoutAdapter);
Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());
mWorkoutAdapter.setWorkoutData(mWorkoutList);
So till the data has not come the listsize will display 0 and then after you get the data in onComplete() list size will increase(). So basically add a line mWorkoutAdapter.notifyDatasetChanged(); here:-
if(task.isSuccessful()){
for (QueryDocumentSnapshot document : task.getResult()){
OtherWorkout workout = document.toObject(OtherWorkout.class);
mWorkoutList.add(workout);
Log.i("LOG", "workout list size: " + mWorkoutList.size());
}mWorkoutAdapter.notifyDatasetChanged();
}
This will refresh your Adapter with your new values.
Upvotes: 2
Reputation: 897
You can check your
Log.i("LOG", "workout list size: " + mWorkoutList.size());
after
Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());
so it means firebase take some some time for fetch all data , in period of this time your rest of code are executed. so the solution is called initDatabaseData() after set the adapter then adapter.notifydatasetchanged() called. or you can direct notify the adapter in initDatabaseData() method after fetching data.
Upvotes: 0
Reputation: 74
You create OtherWorkout
as a local object, then add it to the collection.
If your get()
function runs out of scope the object will be automatically deleted.
I didn't check but I think the Java garbage collection will take care of the rest and delete the object from the Array.
You should create the objects on the Heap with new
so they will persist outside of the scope of that function.
Upvotes: 0