RecyclerView不显示数据库数据 求技术排查
之前可正常向餐食数据库添加新条目并显示在列表中,修复列表删除功能后,新输入的数据虽已写入数据库,但RecyclerView仅显示空白。尝试多种notifyDataSetChanged()调用方式仍无效,怀疑问题出在MainActivity或RatedDishAdapter中,相关代码如下:
MainActivity.java
package com.example.restaurantrater; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { EditText Restaurant_name; EditText Restaurant_address; Button save_btn; private RestaurantDBhelper dbHelper; private RecyclerView recyclerView; private RatedDishAdapter adapter; private static int restIDcount = 0; private ArrayList<RatedDish> ratedDishes; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbHelper = new RestaurantDBhelper(this); Restaurant_name = findViewById(R.id.restaurant_name); Restaurant_address = findViewById(R.id.streetaddress); save_btn = findViewById(R.id.save_dish); save_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String nrestaurant_n = Restaurant_name.getText().toString(); String nrestaurant_a = Restaurant_address.getText().toString(); restIDcount++; // Insert restaurant details into the database long result = dbHelper.insertRestaurant(nrestaurant_n, nrestaurant_a); if (result != -1) { // Restaurant inserted successfully, navigate to DishRater Intent intent = new Intent(MainActivity.this, DishRater.class); intent.putExtra("restaurantid", restIDcount); startActivity(intent); } else { // Failed to insert restaurant // Handle error, show toast or log error } } }); // RecyclerView setup recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); // Initialize adapter for RecyclerView ratedDishes = new ArrayList<>(); adapter = new RatedDishAdapter(ratedDishes, this); recyclerView.setAdapter(adapter); // Set up click listener for delete actions in the adapter adapter.setOnItemClickListener(new RatedDishAdapter.OnItemClickListener() { @Override public void onItemClick(int position) { // Handle item click if needed } @Override public void onDeleteClick(int position) { RatedDish deletedDish = ratedDishes.get(position); boolean isDeleted = dbHelper.deleteDish(deletedDish.getId()); if (isDeleted) { Toast.makeText(MainActivity.this, "Dish deleted successfully", Toast.LENGTH_SHORT).show(); // Remove the deleted item from the RecyclerView ratedDishes.remove(position); adapter.notifyItemRemoved(position); } else { Toast.makeText(MainActivity.this, "Failed to delete dish", Toast.LENGTH_SHORT).show(); } } }); } @Override protected void onResume() { super.onResume(); // Retrieve list of rated meals from the database retrieveRatedDishesFromDatabase(); // Update the adapter with the new list of rated dishes adapter.updateData(ratedDishes); } private void retrieveRatedDishesFromDatabase() { // Call getAllRatedDishes() method from RestaurantDBhelper ratedDishes.clear(); ratedDishes.addAll(dbHelper.getAllRatedDishes()); adapter.updateData(ratedDishes); } }
RatedDishAdapter.java
package com.example.restaurantrater; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; public class RatedDishAdapter extends RecyclerView.Adapter<RatedDishAdapter.RatedDishViewHolder> { private ArrayList<RatedDish> ratedDishes; private OnItemClickListener clickListener; // Define listener private Context context; // Add context field private RestaurantDBhelper dbHelper; // Add dbHelper field public RatedDishAdapter(ArrayList<RatedDish> ratedDishes, Context context) { this.ratedDishes = ratedDishes; this.context = context; // Initialize context this.dbHelper = new RestaurantDBhelper(context); // Initialize dbHelper } public interface OnItemClickListener { void onItemClick(int position); void onDeleteClick(int position); } public void setOnItemClickListener(OnItemClickListener listener) { this.clickListener = listener; } @NonNull @Override public RatedDishViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_rated_dish, parent, false); return new RatedDishViewHolder(itemView); } @Override public void onBindViewHolder(@NonNull RatedDishViewHolder holder, int position) { RatedDish ratedDish = ratedDishes.get(position); holder.textDishName.setText(ratedDish.getName()); holder.textRating.setText(String.valueOf(ratedDish.getRating())); // Set click listener for the delete button holder.deleteButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (clickListener != null) { int position = holder.getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { clickListener.onDeleteClick(position); } } } }); } @Override public int getItemCount() { return ratedDishes.size(); } public class RatedDishViewHolder extends RecyclerView.ViewHolder { public TextView textDishName; public TextView textRating; public Button deleteButton; public RatedDishViewHolder(@NonNull View itemView) { super(itemView); textDishName = itemView.findViewById(R.id.textViewDishName); textRating = itemView.findViewById(R.id.textViewRating); deleteButton = itemView.findViewById(R.id.buttonDelete); // Set click listener for the delete button deleteButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (clickListener != null) { int position = getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { clickListener.onDeleteClick(position); } } } }); // Set click listener on the item view itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (clickListener != null) { int position = getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { clickListener.onItemClick(position); } } } }); } } // Update the data in the adapter public void updateData(ArrayList<RatedDish> newData) { ratedDishes.clear(); ratedDishes.addAll(newData); notifyDataSetChanged(); } }
核心问题及修复方案
1. 重复调用updateData导致数据被清空
在onResume方法中,你先调用了retrieveRatedDishesFromDatabase(),这个方法内部已经调用了adapter.updateData(ratedDishes),而之后又在onResume里再次调用adapter.updateData(ratedDishes)。由于updateData方法会先执行ratedDishes.clear(),等于刚从数据库加载的数据立刻被清空,最终RecyclerView没有数据可显示。
修复:
修改onResume方法,移除重复的updateData调用:
@Override protected void onResume() { super.onResume(); retrieveRatedDishesFromDatabase(); }
2. 潜在问题:餐厅ID维护错误
你用静态变量restIDcount维护餐厅ID,App重启后这个值会重置为0,导致传递给DishRater的ID错误。应该直接使用数据库插入返回的result值(这是数据库自动生成的主键ID):
long result = dbHelper.insertRestaurant(nrestaurant_n, nrestaurant_a); if (result != -1) { Intent intent = new Intent(MainActivity.this, DishRater.class); intent.putExtra("restaurantid", (int)result); // 使用数据库返回的真实ID startActivity(intent); }
3. 重复设置删除按钮监听
在RatedDishAdapter中,你同时在onBindViewHolder和RatedDishViewHolder构造方法里设置了删除按钮的点击监听,会导致点击事件被重复触发。修复: 移除onBindViewHolder中的删除按钮监听代码,只保留ViewHolder构造里的监听即可。
内容的提问来源于stack exchange,提问作者Emmanual Kingston

