从Firebase最佳实践中删除节点

时间:2017-07-15 12:34:09

标签: android firebase firebase-realtime-database

我做了一个firebase项目,我有2个Android应用程序连接到同一个数据库,让我们说第一个应用程序是一个“用户应用程序”,我正在分发给一些朋友,第二个是“管理员应用程序”(一个仅在我的个人电话上的应用程序)。 “用户应用程序”基本上只显示一些关于我所在城市事件的信息,而我使用“管理应用程序”从数据库中添加/删除这些事件

在我的用户应用程序中,我有一个非常标准的RecyclerView,使用FirebaseRecyclerAdapter显示一些卡片。单击一张卡片会弹出一个新的Activity,它会显示有关该事件的更多信息,使用Intent我将一个Id作为一个String传递,它会在数据库中加载相应的节点,一切正常。问题是,当我删除一个节点(来自Firebase控制台或amy“admin”应用程序)时,我的recyclerview中的“卡”仍然可用,点击它会导致NullPointerExeption,因为我正在寻找的对象显然不再在数据库中。

我在我的DatabaseReference上使用.keepSynced(true),我设置了setPersistanceEnabled,我认为这可能是问题所在。

我的适配器声明@OnStart看起来像这样:

if(recyclerView.getAdapter == null){         
eventAdapter = new FirebaseRecyclerAdapter<DynamicData,EventViewHolder>
           (
            DynamicData.class,
            R.layout.event_card,
            EventViewHolder.class,
            eventRef.orderByChild("eName")
            ){

        @Override
        protected void populateViewHolder(EventViewHolder viewHolder, DynamicData model, int position) {
            final String post_key = getRef(position).getKey();
            viewHolder.setDate(model.getDate());
            viewHolder.setId(post_key);
            viewHolder.setName(model.geteName());
            viewHolder.setTime(model.getDate());
            viewHolder.mView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent toEvent = new Intent(getActivity(), EditEvent.class);
                    toEvent.putExtra("EVENT_ID",post_key);
                    startActivity(toEvent);
                }
            });
        }
    };
}

   recyclerView.setAdapter(eventAdapter);
   if(rcState != null){
     recyclerView.getLayoutManager().onRestoreInstanceState(rcState);
   }

所以这里真的没什么奇怪的。

我的OnSavedInstanceState:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putParcelable(BUNDLE_RECYCLER_LAYOUT, linearLayoutManager.onSaveInstanceState());
    rcState = outState.getParcelable(BUNDLE_RECYCLER_LAYOUT);
}

我使用OnStart togheter和onSavedInstanceState中的代码的if(recyclerView.getAdapter()== null)子句是唯一使我的Recycler视图滚动到正确位置的东西。没有这个代码,每当我用Intent更改活动时(通过点击recyclerView项目)然后返回,Recyclerview会重新创建并从顶部再次启动

重要:现在我正在打电话

@Override
public void onDestroy() {
    super.onDestroy();
    recyclerView.setAdapter(null);
    eventAdapter.cleanup();
}

而不是onStop(),因为它显然是我在切换活动时保持我的recyclerView位置的唯一方法。

在我的“管理员应用程序”中,当我想从db中删除某些事件时,我使用此代码:

 //Query fetching events older than 6 hours
       Query returnsixHoursOldEvents = 
     eventRef.orderByChild("date").endAt(six_hours_cutoff);
    returnsixHoursOldEvents.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot postSnapshot : dataSnapshot.getChildren()){


                postSnapshot.getRef().removeValue();



            }
        }

现在的问题是,因为我从“管理员应用”中删除了这个事件,所以无法通过我的“用户应用”通知适配器。会发生的事情有时候(似乎是随机发生的)如果我的朋友打开他的应用程序,他仍然可以在他的recyclerview中看到我刚刚删除的事件,但如果他点击它,应用程序崩溃,因为数据库中的节点不再avaible

是keepSynced还是setPersistanceEnabled问题?任何解决方法?

1 个答案:

答案 0 :(得分:1)

在共享数据模型中,很可能一个用户删除了另一个用户仍然看到的数据,特别是当其中一个用户暂时没有连接到Firebase时。您的代码必须处理这种情况。

removeValue()这样的方法不管数据是否存在:它们只是确保在它们执行后数据消失。