kir*_*403 3 android firebase firebase-realtime-database
我在Activity的onCreate方法中设置了一个值事件监听器.在该方法中,我将数据记录到控制台.我打开了活动,一切正常.但是,如果我关闭活动并更改数据,它仍会被调用,我可以在日志中看到它.
因此,如果我打开该活动说5次,则在每次更新时我会看到5条日志消息.
是否有任何解决方案,我们可以提供该活动的上下文,以便听众在活动结束时死亡.
rootRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.v(TAG, "Data Changed in Activity2");
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
Run Code Online (Sandbox Code Playgroud)
我还需要在RecyclerView中提供太多的值监听器.滚动后,它还会导致多个值更改的事件调用.因为它绑定了现有位置的新谎言,并且没有从onViewRecycled方法中删除的引用.因此,它们被多次调用并在屏幕上随机更改数据.
拥有上下文可以更轻松地设置值事件侦听器.有没有办法跟踪所有听众?也没有方法可以让听众获得参考.
由于目前无法为侦听器提供上下文,因此需要跟踪所有连接的侦听器并将其删除,如David在答案中所示:https://stackoverflow.com/a/33782474/1820644
为了管理内部的价值听众,RecyclerView我提出了一个运作良好的解决方案.我正在使用FirebaseUI的RecyclerView,但解决方案应该适用于每一个RecyclerView.
第1步:首先Map<String,ValueEventListener>在您的活动中创建一个全局:
HashMap<String, ValueEventListener> mRecyclerViewFirebaseListeners = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)
第2步:绑定ValueEventListener的populateViewHolder(在firebaseUI)或onBindViewHodler并将其添加到我们的地图mRecyclerViewFirebaseListeners.另外,Tag使用我们的键的值附加a 到视图持有者
protected void populateViewHolder(final ViewHolder viewHolder,
Boolean model, int position) {
Log.v(TAG, "Populating viewHolder for position: " + position);
// Get the key and add listener
String key = this.getRef(position).getKey();
ValueEventListener listener = mRootRef.child("events").child(key)
.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
Log.v(TAG, "Event Data Change");
// ...
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.v(TAG, databaseError.getMessage());
}
});
Log.v(TAG, "Listener set for event key: " + key + " (position: " +
position + ")");
// Add to our map and set tag on view holder
mRecyclerViewFirebaseListeners.put(key, listener);
viewHolder.itemView.setTag(R.id.TAG_RCV_EVENT_KEY, key);
Log.d(TAG, "Added tag for position:" + position);
// do other work here
}
Run Code Online (Sandbox Code Playgroud)
步骤3:在回收视图时删除视图持有者的侦听器.
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
// Get key from the view holder
String key = (String) holder.itemView.getTag(R.id.TAG_RCV_EVENT_KEY);
Log.v(TAG, "Recycling view set for key: " + key);
// Remove listener for the retrieved key and also remove it from our map
mRootRef.child("events").child(key)
.removeEventListener(mRecyclerViewFirebaseListeners.get(key));
mRecyclerViewFirebaseListeners.remove(key);
Log.v(TAG, "On View Recycled, Removed Event listener for key: " + key);
// ...
}
Run Code Online (Sandbox Code Playgroud)
第4步:删除剩余的侦听器onDestroy()
@Override
public void onDestroyView() {
super.onDestroyView();
// Iterate over map and remove listeners for the key
for (Map.Entry<String, ValueEventListener> entry : mRecyclerViewFirebaseListeners.entrySet()) {
String key = entry.getKey();
ValueEventListener value = entry.getValue();
mRootRef.child("events").child(key).removeEventListener(value);
Log.v(TAG, "Removed Event listener for key: " + key);
}
}
Run Code Online (Sandbox Code Playgroud)
这将从回收站视图中删除所有侦听器.
如果除了recyclerview之外还有更多的值侦听器,请为其他人使用新映射,如果它与同一路径的键模式匹配,则将其合并到此映射中.
或者,您可以将完整路径而不仅仅是一个键作为Map的键.像例如,在我们使用以下儿童"关键"的价值事件作为地图的关键,但你可以把events/<key>一个地图的钥匙,和一个删除去onDestroy用mRootRef.child("<your_combined_key_from_map>").removeListener(listener).
希望这有助于某人.
| 归档时间: |
|
| 查看次数: |
944 次 |
| 最近记录: |