Android Studio中从RecyclerView向SQLite插入数据及收藏按钮SharedPreferences配置问题
问题解决方案
1. 解决「no such table: favorites」报错
这个报错是因为旧版本的数据库文件已经存在于你的手机/模拟器中,SQLiteOpenHelper的onCreate方法只会在数据库第一次创建的时候执行,你后续修改了建表逻辑但没有升级数据库版本,导致favorites表没有被创建:
- 临时测试解决:直接卸载当前APP重新安装,旧的数据库文件会被清除,第一次启动会触发
onCreate建表 - 正式修复:将FavDB构造方法中的数据库版本号从
1改为2,触发onUpgrade方法删除旧表重建:
public FavDB(Context context) { super(context, DB_NAME, null, 2); // 版本号从1改到2 }
2. 解决db.insert返回-1的问题
表创建成功后这个问题会自动消失,如果还有返回-1的情况,检查以下两点:
- 确认插入的FavVenueItem所有字段都不为空,你当前初始化的数据都是全的,不会有这个问题
- 可选优化:表中image字段当前定义为TEXT类型,但你插入的是int类型的资源ID,建议将建表语句中的image字段改为INTEGER类型,避免后续类型不匹配问题:
db.execSQL(" CREATE TABLE " +TABLE_NAME + "(" + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + Venue_name + " TEXT, " +Venue_type+ " TEXT, " +Venue_budget+ " TEXT, "+Venue_image+ " INTEGER, "+Venue_contact+ " TEXT, "+FAV_STATUS+ " TEXT)");
3. 优化收藏逻辑&添加状态持久化
3.1 修复按钮状态错乱问题
你当前在onBindViewHolder中没有设置收藏按钮的初始状态,RecyclerView滑动复用条目时会出现状态错乱,修改onBindViewHolder代码:
@Override public void onBindViewHolder(@NonNull @NotNull ViewHolder holder, int position) { final FavVenueItem venueItem = VenueItemsList.get(position); holder.ImageView.setImageResource(venueItem.getImageResourse()); holder.Name.setText(venueItem.getVenuename()); holder.venuetype.setText(venueItem.getType()); holder.venuebudget.setText(venueItem.getBudget()); holder.venuecontact.setText(venueItem.getContact()); // 新增:根据收藏状态设置按钮图标 if(venueItem.getFavStatus().equals("1")){ holder.favbtn.setBackgroundResource(R.drawable.ic_baseline_favorite_24); }else{ holder.favbtn.setBackgroundResource(R.drawable.ic_baseline_favorite_border_24); } }
3.2 补全取消收藏逻辑
你当前代码中取消收藏时没有删除数据库中的对应记录,收藏Fragment中会一直显示已经取消的条目,修改ViewHolder中点击事件的else分支:
} else { venueItem.setFavStatus("0"); // 新增:删除数据库中对应的收藏记录 SQLiteDatabase db = favDB.getWritableDatabase(); db.delete(FavDB.TABLE_NAME, FavDB.Venue_name + "=?", new String[]{venueItem.getVenuename()}); favbtn.setBackgroundResource(R.drawable.ic_baseline_favorite_border_24); }
3.3 添加SharedPreferences状态存储(可选)
如果需要用SharedPreferences存储收藏状态(更推荐直接从数据库读状态,SP适合少量配置存储),实现如下:
首先在Adapter中初始化SharedPreferences:
private SharedPreferences sp; public VenueAdapter(ArrayList<FavVenueItem> VenueItems, Context context) { this.VenueItemsList = VenueItems; this.context = context; sp = context.getSharedPreferences("fav_sp", Context.MODE_PRIVATE); }
点击收藏时存储状态:
if (venueItem.getFavStatus().equals("0")) { venueItem.setFavStatus("1"); favDB.inserttVenueData(venueItem); // 存储SP状态,用场馆名作为key sp.edit().putString(venueItem.getVenuename(), "1").apply(); favbtn.setBackgroundResource(R.drawable.ic_baseline_favorite_24); } else { venueItem.setFavStatus("0"); SQLiteDatabase db = favDB.getWritableDatabase(); db.delete(FavDB.TABLE_NAME, FavDB.Venue_name + "=?", new String[]{venueItem.getVenuename()}); // 删除SP中对应的状态 sp.edit().remove(venueItem.getVenuename()).apply(); favbtn.setBackgroundResource(R.drawable.ic_baseline_favorite_border_24); }
加载列表时从SP读取初始状态:
// 在setData方法之后或者onBindViewHolder中读取 String favStatus = sp.getString(venueItem.getVenuename(), "0"); venueItem.setFavStatus(favStatus);
内容的提问来源于stack exchange,提问作者Neha M.
相关产品推荐
相关产品推荐

