首页 > 解决方案 > 使用 recyclerview 的“onChildRemoved”方法出错

问题描述

我正在用来自 firebase 的数据填充我的 recyclerview(它被放入一个卡片视图中,上面有 3 个文本视图)。当我从 Firebase 中删除它时,它仍会显示在应用程序中,除非我重新启动它。我尝试在 onChildRemoved 方法中做一些事情,但我不断收到错误消息。这是我的错误(运行“list.remove(index)”时发生):

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.samuelford48gmail.thsconnect, PID: 11463
java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
    at java.util.ArrayList.remove(ArrayList.java:506)
    at com.samuelford48gmail.thsconnect.home_fragment$1.onChildRemoved(home_fragment.java:140)

这是我的代码:

public class home_fragment extends Fragment{


private FirebaseDatabase database;
private DatabaseReference myRef;

private List<Listdata> list;
private RecyclerView recyclerview;
public home_fragment() {

}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.home_fragment, container, false);
   final List<String> keyList = new ArrayList<String>();
    recyclerview = (RecyclerView) view.findViewById(R.id.rview);
    database = FirebaseDatabase.getInstance();
    myRef = database.getReference("Users")
            .child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("Classes");
    list = new ArrayList<>();
    myRef.addChildEventListener(new ChildEventListener() {
        final adapter_user_remove_class recycler = new adapter_user_remove_class(list);
        @Override
        public void onChildAdded(@NonNull DataSnapshot dataSnapshot, String s) {
            String class_id = dataSnapshot.getValue(String.class);

            myRef = database.getReference("Classes").child(class_id).child("class_info");
            myRef.addValueEventListener(new ValueEventListener() {
  @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    keyList.add(dataSnapshot.getKey());
                        Class_model new_class = dataSnapshot.getValue(Class_model.class);
                        assert new_class != null;
                        String nameofclass = new_class.getDate_clasname();
                        String teacherofclass = new_class.getTeacher();
                        String roomnumberofclass = new_class.getRoom_number();
                        String class_key = new_class.getUid();
                        Listdata listdata = new Listdata(nameofclass, teacherofclass, roomnumberofclass, class_key);
               listdata.setDate_class(nameofclass);
                        listdata.setTeacher(teacherofclass);
                        listdata.setRnumber(roomnumberofclass);
                        list.add(listdata);
                    recycler.notifyDataSetChanged();

                }


                @Override
                public void onCancelled(DatabaseError error) {
                    AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
                    alertDialog.setTitle("Error");
                    alertDialog.setMessage("Check your connection! If, problem persists please email svhsdev@vigoschools.org!");
                    alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                }
                            });
                    alertDialog.show();
                }

            });

    RecyclerView.LayoutManager layoutmanager = new LinearLayoutManager(getContext());
       recyclerview.setLayoutManager(layoutmanager);
           recyclerview.setItemAnimator(new DefaultItemAnimator());
           recyclerview.setAdapter(recycler);



        }
        @Override
        public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}

        @Override
        public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
            int index = keyList.indexOf(dataSnapshot.getKey());

                list.remove(index);
               keyList.remove(index);

            recycler.notifyDataSetChanged();

        }

        @Override
        public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

        }

        @Override
        public void onCancelled(DatabaseError error) {
            AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
            alertDialog.setTitle("Error");
            alertDialog.setMessage("Check your connection! If, problem persists please email svhsdev@vigoschools.org!");
            alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
            alertDialog.show();
        }


    });

    return view;
}
}

这是我的数据库结构:

  {
  "Classes" : {

"-LiGRe3e1YF_HFrHKMgi" : {
  "Students" : {
    "xfDGLrXF4gP8AJAPtAPc4VMe9y72" : "xfDGLrXF4gP8AJAPtAPc4VMe9y72"
  },
  "class_info" : {
    "date_clasname" : "mm",
    "room_number" : "jjhh",
    "subject" : "Science",
    "teacher" : "mm",
    "uid" : "-LiGRe3e1YF_HFrHKMgi"
  }
},


  "Users" : {
    "xfDGLrXF4gP8AJAPtAPc4VMe9y72" : {
    "Classes" : {
    "-LiGRe3e1YF_HFrHKMgi" : "-LiGRe3e1YF_HFrHKMgi",

  },
  "User_info" : {
    "email" : "c@gmail.com",
    "grade" : "2",
    "name" : "n",
    "uid" : "xfDGLrXF4gP8AJAPtAPc4VMe9y72"
  }
}
 }
 }

标签: javaandroidfirebasefirebase-realtime-databaseandroid-recyclerview

解决方案


因此,通常当您处理 Firebase 数据并将其呈现在 RecyclerView 中时,我的偏好是监听 Firebase 数据库中的整个节点。

您将快照中的数据映射到一个列表中,其中 N 是您的数据项的一些 POJO 表示,然后您使用整个列表更新您的适配器。

在适配器内部,可以更新内部列表,然后使用DiffUtil

public class N {
    final String id; // Firebase key

    public N(String id) { }

    public String getId() { return id; }
}

fb.collection("/path/to/collection")
    .addEventListener(snapshot -> {
        List<N> list = new ArrayList();
        for (...) { /* create and add Ns to list */ }
        adapter.setList(list);
    });

// in your adapter...
void setList(List<N> items) {
    List<N> oldList = data;
    data = items;

    // Updates your list, applys animations, etc.
    DiffUtil.calculateDiff(new Callback(oldList, data).dispatchUpdatesTo(this);
}

class Callback implements DiffUtil.Callback {
    // impl, pretty straightforward
}

这样做意味着您不需要在其他地方管理键/值。

https://developer.android.com/reference/android/support/v7/util/DiffUtil


推荐阅读