为什么我的 RecyclerView 显示的列表重复?

问题描述 投票:0回答:1

我有一个带有 RecyclerView 的 Activity,它从我的 Fireabase 数据库获取对象列表。到目前为止,一切都按预期进行。 在适配器上,我有一个按钮可以删除一个对象。此按钮将从列表和数据库中删除对象。

当点击它时,该对象确实从两个地方都被删除了。它重复 RecyclerView 上的列表的问题。

如何解决此问题?

回收商视图

public class ApiariosListActivity extends AppCompatActivity implements ApiarioOnListAdapter.ApiarioClickListener {

    private ApiarioOnListAdapter apiarioOnListAdapter;

    private ArrayList<Apiario> apiList;
    private static final int EDIT_APIARIO_REQUEST_CODE = 1;
    private static final int ADD_APIARIO_REQUEST_CODE = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_apiarios_list);

        RecyclerView recyclerView = findViewById(R.id.recyclerViewApiarios);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        this.apiList = new ArrayList<>();

        DatabaseReference mDatabaseQuery = FirebaseDatabase.getInstance().getReference("apiario");

        Query query = mDatabaseQuery;

        query.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                for(DataSnapshot dataSnapshot : snapshot.getChildren()){

                    Apiario apiario = dataSnapshot.getValue(Apiario.class);
                    apiList.add(apiario);
                }

                apiarioOnListAdapter = new ApiarioOnListAdapter(apiList, ApiariosListActivity.this);
                recyclerView.setAdapter(apiarioOnListAdapter);
            }

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

            }
        });


        // Add Apiario button
        ImageButton btnAddApiario = findViewById(R.id.btnAddApiario);
        btnAddApiario.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(ApiariosListActivity.this, SelectDistrictActivity.class);
                startActivityForResult(intent, ADD_APIARIO_REQUEST_CODE);
            }
        });
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d("AnualDeclarationActivity", "JV: onRestart");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d("AnualDeclarationActivity", "JV: onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("AnualDeclarationActivity", "JV: onResume");
    }

    @Override
    public void onEditClick(Apiario apiario) {
        Log.d("AnualDeclarationActivity", "JV: onEditClick");
        Intent intent = new Intent(this, EditApiarioActivity.class);
        intent.putExtra("apiario", apiario);
        startActivityForResult(intent, EDIT_APIARIO_REQUEST_CODE);
    }

    @Override
    public void onDeleteClick(Apiario apiario) {
        // Implement delete functionality, e.g., show a confirmation dialog
        showDeleteConfirmationDialog(apiario);
    }

    private void showDeleteConfirmationDialog(final Apiario apiario) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Delete Apiario");
        builder.setMessage("Are you sure you want to delete this Apiario?");

        builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                // Perform the delete operation
                deleteApiario(apiario);
            }
        });

        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                // Cancel the delete operation
                dialogInterface.dismiss();
            }
        });

        builder.create().show();
    }

    private void deleteApiario(Apiario apiario) {
        // Remove the apiario from the list
        apiList.remove(apiario);
        // Notify the adapter of the change
        apiarioOnListAdapter.notifyDataSetChanged();
        // Inform the user
        Toast.makeText(this, "Apiario deleted: " + apiario.getNomeApiario(), Toast.LENGTH_SHORT).show();
    }

    private class PostDataTask extends AsyncTask<List<Apiario>, Void, String> {

        @Override
        protected void onPreExecute() {
            Log.d("AsyncTask", "Executing onPreExecute");
        }

        @Override
        protected String doInBackground(List<Apiario>... apiariosList) {
            Log.d("AsyncTask", "Execute doInBackground");

            // Create a JSON array to hold multiple Apiario objects
            JSONArray apiarioArray = new JSONArray();

            // Convert each Apiario object to a JSON object and add it to the array
            for (Apiario apiario : apiariosList[0]) {
                try {
                    JSONObject apiarioObject = new JSONObject();
                    apiarioObject.put("nomeApiario", apiario.getNomeApiario());
                    apiarioObject.put("apiarioDeTransumancia", apiario.isApiarioDeTransumancia()); // Example value, modify as needed
                    apiarioObject.put("numColmeias", apiario.getNumColmeias());
                    apiarioObject.put("numNucleos", apiario.getNumNucleos());
                    apiarioObject.put("coordenadaX", apiario.getCoordenadaX());
                    apiarioObject.put("coordenadaY", apiario.getCoordenadaY());
                    apiarioObject.put("freguesia", apiario.getFreguesia());

                    apiarioArray.put(apiarioObject);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            // Create the main JSON object with the array
            JSONObject mainJsonObject = new JSONObject();
            try {
                mainJsonObject.put("declarationModel", apiarioArray);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            ApiCaller apiCaller = new ApiCaller();
            String apiUrl = "http://10.0.2.2:5176/api/DeclarationController/SubmitAnualDeclaration";
            String jsonInputString = mainJsonObject.toString();

            Log.d("AsyncTask", "doInBackground: Making install request with JSON: " + jsonInputString);

            String result = apiCaller.makePost(apiUrl, jsonInputString);

            if (result != null) {
                Log.d("AsyncTask", "doInBackground: Submission successful. Response: " + result);
                return result;
            } else {
                Log.d("AsyncTask", "doInBackground: Submission request failed.");
                return null;
            }
        }

        @Override
        protected void onPostExecute(String result) {
            Log.d("AsyncTask", "FP : Executing onPostExecute");
            if (result != null) {
                Toast.makeText(ApiariosListActivity.this, "Success", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(ApiariosListActivity.this, "Error", Toast.LENGTH_LONG).show();
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d("TEST", "JV: onActivityResult - requestCode: " + requestCode + ", resultCode: " + resultCode);
        Log.d("TEST", "JV: ON ACTIVITY");

        if (requestCode == ADD_APIARIO_REQUEST_CODE && resultCode == RESULT_OK && data != null) {
            // Retrieve the newly added Apiario object
            Apiario newApiario = data.getParcelableExtra("newApiario");

            // Add the new Apiario to the list
            apiList.add(newApiario);

            // Notify the adapter of the change
            apiarioOnListAdapter.notifyDataSetChanged();
        }

        if (requestCode == EDIT_APIARIO_REQUEST_CODE && resultCode == RESULT_OK && data != null) {
            Apiario modifiedApiario = data.getParcelableExtra("modifiedApiario");
            int position = findPositionOfApiarioInList(modifiedApiario);
            if (position != -1) {
                apiList.set(position, modifiedApiario);
                apiarioOnListAdapter.notifyItemChanged(position);
            }
        }
    }

    private int findPositionOfApiarioInList(Apiario apiario) {
        for (int i = 0; i < apiList.size(); i++) {
            if (apiList.get(i).getNomeApiario().equals(apiario.getNomeApiario())) {
                return i;
            }
        }
        return -1;
    }

}

适配器

public class ApiarioOnListAdapter extends RecyclerView.Adapter<ApiarioOnListAdapter.ApiarioViewHolder> {

    private List<Apiario> apiarios;
    private ApiarioClickListener listener;

    public interface ApiarioClickListener {
        void onEditClick(Apiario apiario);
        void onDeleteClick(Apiario apiario);
    }

    public ApiarioOnListAdapter(List<Apiario> apiarios, ApiarioClickListener listener) {
        this.apiarios = apiarios;
        this.listener = listener;
    }

    public class ApiarioViewHolder extends RecyclerView.ViewHolder {
        TextView textName;
        TextView textEstado;

        Button btnEdit;
        Button btnDelete;
        LinearLayout buttonContainer; // Add this line

        public ApiarioViewHolder(@NonNull View itemView) {
            super(itemView);
            textName = itemView.findViewById(R.id.textName);
            textEstado = itemView.findViewById(R.id.textEstado);

            btnEdit = itemView.findViewById(R.id.btnEdit);
            btnDelete = itemView.findViewById(R.id.btnDelete);
            buttonContainer = itemView.findViewById(R.id.buttonContainer);
        }
    }

    @NonNull
    @Override
    public ApiarioViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.apiario_item_list, parent, false);
        return new ApiarioViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull ApiarioViewHolder holder, int position) {
        final Apiario apiario = apiarios.get(position);

        holder.textName.setText("Nome: " + apiario.getNomeApiario());
        holder.textEstado.setText("Estado: " + apiario.getEstado());

        holder.btnEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Apiario selectedApiario = apiarios.get(holder.getAdapterPosition());
                Log.d("TEST", "JV: SELECTED " + selectedApiario.getNomeApiario());
                listener.onEditClick(selectedApiario);
            }
        });

        holder.btnDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //listener.onDeleteClick(apiario);
                int apiarioId = apiario.getID();
                Log.d("TEST", "JV: ID A REMOVER " + apiarioId);

                DatabaseReference apiarioRef = FirebaseDatabase.getInstance().getReference("apiario");

                Query query = apiarioRef.orderByChild("id").equalTo(apiarioId);

                query.addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot snapshot) {
                        for (DataSnapshot data : snapshot.getChildren()) {
                            String apiarioId = data.getKey();
                            Log.d("TEST", "JV: ENTRA NO FOR DA REMOÇAO " + apiarioId);
                            // Obtém a referência do banco de dados para o nó 'apiario' usando o ID do apiário
                            DatabaseReference apiarioToRemoveRef = apiarioRef.child(apiarioId);

                            // Remove o nó 'apiario' da base de dados
                            apiarioToRemoveRef.removeValue();

                            // Opcional: Remover o APIário da lista local
                            apiarios.remove(apiario);

                            // Notificar o adapter sobre a mudança nos dados
                            notifyDataSetChanged();


                        }
                    }

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

                    }
                });
            }
        });

        // Check if the state is "Pendente" and add a button dynamically
        if (apiario.getEstado().equalsIgnoreCase("Pendente")) {
            Button customButton = new Button(holder.itemView.getContext());
            customButton.setText("Confirmar");
            // Add the button to the layout
            holder.buttonContainer.addView(customButton);
            // Set a click listener for the custom button
            customButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // Handle button click
                    // You can perform specific actions based on the button click
                    DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference("apiario");
                    Query query = mDatabase.orderByChild("id").equalTo(apiario.getID());

                    query.addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot snapshot) {

                            for (DataSnapshot data : snapshot.getChildren()){

                                String confirmID = data.getKey();
                                mDatabase.child(confirmID).child("estado").setValue("Aceite");
                                holder.buttonContainer.removeAllViews();

                                // Atualizar o estado na lista local
                                apiario.setEstado("Aceite");

                                // Notificar o adapter sobre a mudança nos dados
                                notifyDataSetChanged();

                            }


                        }

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

                        }
                    });


                }
            });
        } else {
            // If the state is not "Pendente", make sure to remove any previously added button
            holder.buttonContainer.removeAllViews();
        }
    }

    private void openEditApiarioActivity(Context context, Apiario apiario) {
        Intent intent = new Intent(context, EditApiarioActivity.class);
        intent.putExtra("apiario", apiario);
        context.startActivity(intent);
    }

    @Override
    public int getItemCount() {
        return apiarios.size();
    }
}
java android firebase-realtime-database android-recyclerview android-adapter
1个回答
0
投票

问题就在这里:

protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_apiarios_list);

    RecyclerView recyclerView = findViewById(R.id.recyclerViewApiarios);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    this.apiList = new ArrayList<>(); // 👈

    DatabaseReference mDatabaseQuery = FirebaseDatabase.getInstance().getReference("apiario");

    Query query = mDatabaseQuery;

    query.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            for(DataSnapshot dataSnapshot : snapshot.getChildren()){

                Apiario apiario = dataSnapshot.getValue(Apiario.class);
                apiList.add(apiario); // 👈
            }

            apiarioOnListAdapter = new ApiarioOnListAdapter(apiList, ApiariosListActivity.this);
            recyclerView.setAdapter(apiarioOnListAdapter);
        }

由于您使用

addValueEventListener
,您的
onDataChange
将使用初始数据“立即”调用,然后每当
query
处的数据发生变化时再次调用。但是您只创建一个新的空列表一次(在
onCreate
中),因此每次调用
onDataChange
时,您都会将项目添加到已填充的列表中。

更好的实现是:

protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_apiarios_list);

    RecyclerView recyclerView = findViewById(R.id.recyclerViewApiarios);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    this.apiList = new ArrayList<>();

    DatabaseReference mDatabaseQuery = FirebaseDatabase.getInstance().getReference("apiario");

    Query query = mDatabaseQuery;

    query.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            apiList.clear(); // 👈 Clear previous results
            for(DataSnapshot dataSnapshot : snapshot.getChildren()){

                Apiario apiario = dataSnapshot.getValue(Apiario.class);
                apiList.add(apiario);
            }

            apiarioOnListAdapter = new ApiarioOnListAdapter(apiList, ApiariosListActivity.this);
            recyclerView.setAdapter(apiarioOnListAdapter);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            throw error.toException(); // 👈 Never ignore errors
        }
    });
© www.soinside.com 2019 - 2024. All rights reserved.