简体   繁体   中英

NotifyDataSetChanged doesn't update if it isn't in the loop adding the data

I'm updating a basic leaderboard ListView using firebase data. It updates whenever any users score changes.

I have a listView:

ListView lvLeaderboard;
lvLeaderboard = findViewById(R.id.lvLeaderboard);

An ArrayList: ArrayList<String> userLeaderboardStrings = new ArrayList<>();

An ArrayAdapter:

ArrayAdapter<String> leaderboardAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, userLeaderboardStrings);

The data loads fine. Thing is, if I don't place the leaderboardAdapter.notifyDatSetChanged() in the loop that iterates over the firebase data and adds it in the adapter then it won't update.

But the reason I'm taking it out of the loop is to update the list once all the data's been loaded.

See, my first approach was to clear the list before querying the database:

leaderboardAdapter.clear();

and then query for each users data. This left a small window where the ListView wasn't drawn at all, because the data was being fetched. Coupled with the fact that the Firebase data updates super quick(you tap a button to increase your score, and so you tap it as fast as you can), it's always updating, and hence, always flickering away and not displayed for longer than a 10th of a second.

But adding it outside of the snapshot iterator wont run it.

How can I refresh the listview once ALL data's been loaded?


//NOTE: this is all in an enclosing valueEventListener onDataChange Method

userLeaderboardStrings.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {                            
    usersListRef.child(snapshot.getKey()).addListenerForSingleValueEvent(new 
    ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            Map<String, Object> userCredMap = (Map<String, Object>) 
            dataSnapshot.getValue();
            userLeaderboardStrings.add(just the name + score);                                        
            leaderboardAdapter.notifyDataSetChanged(); // This line
    }
       @Override
       public void onCancelled(@NonNull DatabaseError databaseError) {
        }
     });
   }
//I wanna put the notifyDataSetChanged Here. It wont work
    userLeaderboardStrings.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {                            
    usersListRef.child(snapshot.getKey()).addListenerForSingleValueEvent(new 
    ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            Map<String, Object> userCredMap = (Map<String, Object>) 
            dataSnapshot.getValue();
            userLeaderboardStrings.add(just the name + score);                                        
            leaderboardAdapter.notifyDataSetChanged(); // This line
    }
       @Override
       public void onCancelled(@NonNull DatabaseError databaseError) {
        }
     });
   }

This event addListenerForSingleValueEvent runs asynchronously, for each iteration it is creating a new instance of addListenerForSingleValueEvent and notifying ListView after each successful call of onDataChange .

Therefore it is working fine while placing it inside the loop.

But if you want it to be outside the loop then, in that case, you have to check whether all the addListenerForSingleValueEvent completed or not and after completion of them you need to notify the list. But this approach seems to be not very effective and good.

What you had done above is fine. Hope you understand what I was trying to explain above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM