简体   繁体   English

如果NotifyDataSetChanged不在循环中添加数据,则不会更新

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

I'm updating a basic leaderboard ListView using firebase data. 我正在使用Firebase数据更新基本排行榜ListView。 It updates whenever any users score changes. 每当任何用户得分变化时,它都会更新。

I have a listView: 我有一个listView:

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

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

An ArrayAdapter: 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. 问题是,如果我不将leaderboardAdapter.notifyDatSetChanged()放在迭代firebase数据并将其添加到适配器的循环中,则它将不会更新。

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. 这留下了一个小窗口,根本没有绘制ListView,因为正在获取数据。 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. 加上Firebase数据更新速度超级快(您点击按钮以提高得分,因此您可以尽可能快地点击它),它总是在更新,因此总是闪烁不亮,显示时间不会超过十分之一秒。

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 . 此事件addListenerForSingleValueEvent异步运行,对于每次迭代,它将创建一个addListenerForSingleValueEvent的新实例,并在每次成功调用onDataChange之后通知ListView。

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. 但是,如果您希望它不在循环中,那么在这种情况下,您必须检查所有的addListenerForSingleValueEvent是否都已完成,并且在完成之后,您需要通知该列表。 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. 希望您理解我在上面试图解释的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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