簡體   English   中英

從實時數據庫中刪除值時出現 java.lang.IndexOutOfBoundsException

[英]java.lang.IndexOutOfBoundsException when removing value from Realtime Database

我有一個應用程序顯示用戶從 Firebase 實時數據庫到 Android Studio RecycleView 的項目。 對於 RecycleView 中的每個項目,我添加了一個 function 供用戶刪除他們想要刪除的項目。

我正在使用fridgeRef.child(getRef(position).getKey()).removeValue(); 刪除該值。 我在 Firebase 中的 JSON 結構是

 {
  "Ingredient": {
    "hgO9joLhmfh4Wjn7xYpyqcYmNOB3": {
      "Cashews": {
        "Expiry": "2023-01-21",
        "Ingredient": 1
      },
      "Macadamia Nuts": {
        "Expiry": "2022-11-22",
        "Ingredient": 1
      },
      "Pecans": {
        "Expiry": "2023-01-21",
        "Ingredient": 1
      },
      "Pine Nuts": {
        "Expiry": "2022-11-22",
        "Ingredient": 1
      },
      "Pistachios": {
        "Expiry": "2023-01-21",
        "Ingredient": 1
      }
    }
  }
}

這里的問題,我嘗試刪除第一個值是Cashew,它會成功刪除,但是我嘗試刪除Macadamia Nuts,它將是它下面的數據是Pecans。 問題一直存在,直到澳洲堅果離開我嘗試刪除它會顯示此錯誤並且應用程序將強制停止

java.lang.IndexOutOfBoundsException: Index: 4, Size: 3 at java.util.ArrayList.get(ArrayList.java:437) at com.firebase.ui.common.BaseObservableSnapshotArray.getSnapshot(BaseObservableSnapshotArray.java:70) at com. firebase.ui.database.FirebaseRecyclerAdapter.getRef(FirebaseRecyclerAdapter.java:114) at com.example.recipely.fridge$2.lambda$onBindViewHolder$0$com-example-recipely-fridge$2(fridge.java:163) at com.example .recipely.fridge$2$$ExternalSyntheticLambda0.onClick(未知來源:4)

冰箱.java

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        ingredientView = inflater.inflate(R.layout.fragment_fridge, container, false);

        expiryNote = (LinearLayout) ingredientView.findViewById(R.id.expiryNote);
        HaveData = (ScrollView) ingredientView.findViewById(R.id.HaveData);
        noFridge = (LinearLayout) ingredientView.findViewById(R.id.noFridge);

        expiryNote.setVisibility(View.GONE);
        HaveData.setVisibility(View.GONE);
        myIngredientList = (RecyclerView) ingredientView.findViewById(R.id.ingredientList);
        myIngredientList.setLayoutManager(new LinearLayoutManager(getContext()));

        mAuth = FirebaseAuth.getInstance();
        currentUserID = mAuth.getCurrentUser().getUid();

        fridgeRef = FirebaseDatabase.getInstance().getReference().child("Ingredient").child(currentUserID);

        fridgeRef.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if(snapshot.exists()){
                    HaveData.setVisibility(View.VISIBLE);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });

        return ingredientView;
    }

    @Override
    public void onStart() {
        super.onStart();


        FirebaseRecyclerOptions<fridgeItem> options =
                new FirebaseRecyclerOptions.Builder<fridgeItem>()
                        .setQuery(fridgeRef , fridgeItem.class)
                        .build();

        FirebaseRecyclerAdapter<fridgeItem, fridgeViewHolder> adapter
                = new FirebaseRecyclerAdapter<fridgeItem, fridgeViewHolder>(options) {
            @Override
            protected void onBindViewHolder(@NonNull fridgeViewHolder holder, int position, @NonNull fridgeItem model) {
                String itemName = getRef(position).getKey();

                LocalDate expiry = LocalDate.parse(model.getExpiry());
                LocalDate today = LocalDate.now();
                long dayDiff = DAYS.between(today, expiry);

                if(dayDiff <= 7){
                    holder.cardViewIngredient.setBackgroundColor(Color.parseColor("#FFD1D1"));
                    expiryNote.setVisibility(View.VISIBLE);
                }
                holder.ingredName.setText(itemName);
                holder.ingredExpiry.setText(dayDiff + " Days until expiry");

                holder.deleteBtn.setOnClickListener(v ->{
                    String output = fridgeRef.child(getRef(position).getKey()).toString();
                    Log.d("Fridge" , output );
                    fridgeRef.child(getRef(position).getKey()).removeValue();
                });
            }

            @NonNull
            @Override
            public fridgeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.ingredientrecycle, parent, false);
                fridgeViewHolder viewHolder = new fridgeViewHolder(view);
                return viewHolder;
            }
        };

        myIngredientList.setAdapter(adapter);
        adapter.startListening();
    }

    public static class fridgeViewHolder extends RecyclerView.ViewHolder{

        TextView ingredName, ingredExpiry;
        LinearLayout deleteBtn, cardViewIngredient;

        public fridgeViewHolder(@NonNull View itemView) {
            super(itemView);


            ingredName = itemView.findViewById(R.id.itemName);
            ingredExpiry = itemView.findViewById(R.id.itemExpiry);

            cardViewIngredient = itemView.findViewById(R.id.cardViewIngredient);
            //set button to delete an item
            deleteBtn = itemView.findViewById(R.id.deleteItem);
        }
    }
}

The problem that you are using old positions with the delete function, for example in the beginning Pistachios is at position 4 but if you delete the other item it will became at position 0, that's why you get the error, the problem is on onBindViewHolder :

@Override
protected void onBindViewHolder(@NonNull fridgeViewHolder holder, int position, @NonNull fridgeItem model) {
    // the correct itemName is going to be stored here
    String itemName = getRef(position).getKey();

    LocalDate expiry = LocalDate.parse(model.getExpiry());
    LocalDate today = LocalDate.now();
    long dayDiff = DAYS.between(today, expiry);

    if(dayDiff <= 7){
        holder.cardViewIngredient.setBackgroundColor(Color.parseColor("#FFD1D1"));
        expiryNote.setVisibility(View.VISIBLE);
    }
    holder.ingredName.setText(itemName);
    holder.ingredExpiry.setText(dayDiff + " Days until expiry");

    holder.deleteBtn.setOnClickListener(v ->{
        // and here we will use the correct stored itemName instead of getting a new one
        String output = fridgeRef.child(itemName.toString();
        Log.d("Fridge" , output );
        fridgeRef.child(itemName).removeValue();
    });
}

這應該可以解決您的問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM