如何在Android Studio中为安卓饮品咖啡因应用添加带搜索排序的数据库?
安卓饮品咖啡因信息应用数据库及功能实现方案
一、数据库选型与基础配置
推荐使用Room Persistence Library,安卓官方ORM框架,无需手写复杂SQL,新手友好。
1. 添加依赖
在Module级build.gradle中引入Room依赖:
dependencies { def room_version = "2.6.1" implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" }
2. 创建实体类
对应你的6列数据,创建Drink.java:
@Entity(tableName = "drinks") public class Drink { @PrimaryKey(autoGenerate = true) private int id; private String name; // 饮品名称 private String category; // 饮品类别 private float servingSize; // 份容量 private float totalCaffeine; // 咖啡因总量 private float caffeinePer100ml; // 每100ml咖啡因含量 // 构造方法、getter、setter自行补充 }
3. 定义Dao接口
封装所有数据库操作方法,创建DrinkDao.java:
@Dao public interface DrinkDao { // 用户录入数据 @Insert void insertDrink(Drink drink); // 按指定列升序查询所有数据 @Query("SELECT * FROM drinks ORDER BY :sortColumn ASC") List<Drink> getAllDrinksAsc(String sortColumn); // 按指定列降序查询所有数据 @Query("SELECT * FROM drinks ORDER BY :sortColumn DESC") List<Drink> getAllDrinksDesc(String sortColumn); // 按类别筛选 @Query("SELECT * FROM drinks WHERE category = :category ORDER BY name ASC") List<Drink> getDrinksByCategory(String category); // 搜索(匹配名称或类别) @Query("SELECT * FROM drinks WHERE name LIKE '%' || :searchQuery || '%' OR category LIKE '%' || :searchQuery || '%'") List<Drink> searchDrinks(String searchQuery); }
4. 创建数据库实例
用单例模式避免重复初始化,创建AppDatabase.java:
@Database(entities = {Drink.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract DrinkDao drinkDao(); private static volatile AppDatabase INSTANCE; public static AppDatabase getInstance(Context context) { if (INSTANCE == null) { synchronized (AppDatabase.class) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "drink_database") .build(); } } } return INSTANCE; } }
二、Excel现有数据导入
在App启动时检查数据库,为空则批量插入Excel中的数据:
// 在Application类或首页Activity的onCreate方法中执行 AppDatabase db = AppDatabase.getInstance(this); new Thread(() -> { List<Drink> drinks = db.drinkDao().getAllDrinksAsc("name"); if (drinks.isEmpty()) { // 示例:添加Excel中的一条数据 db.drinkDao().insertDrink(new Drink("冰美式", "现磨咖啡", 350f, 150f, 42.86f)); // 批量添加其余Excel数据... } }).start();
三、核心功能实现
1. 搜索功能
监听搜索框文本变化,实时查询数据:
searchEditText.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { String query = s.toString().trim(); new Thread(() -> { List<Drink> result = db.drinkDao().searchDrinks(query); runOnUiThread(() -> { // 更新RecyclerView适配器数据 drinkAdapter.setData(result); }); }).start(); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} });
2. 按类别筛选
给类别选择控件(如Spinner)添加选择监听:
categorySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String selectedCategory = parent.getItemAtPosition(position).toString(); new Thread(() -> { List<Drink> result; if (selectedCategory.equals("全部")) { result = db.drinkDao().getAllDrinksAsc("name"); } else { result = db.drinkDao().getDrinksByCategory(selectedCategory); } runOnUiThread(() -> drinkAdapter.setData(result)); }).start(); } @Override public void onNothingSelected(AdapterView<?> parent) {} });
3. 数值列排序
给排序按钮添加点击事件,切换升降序:
private boolean isAscending = true; sortButton.setOnClickListener(v -> { isAscending = !isAscending; new Thread(() -> { List<Drink> result; // 示例:按每100ml咖啡因含量排序 if (isAscending) { result = db.drinkDao().getAllDrinksAsc("caffeinePer100ml"); } else { result = db.drinkDao().getAllDrinksDesc("caffeinePer100ml"); } runOnUiThread(() -> { drinkAdapter.setData(result); sortButton.setText(isAscending ? "升序" : "降序"); }); }).start(); });
4. 用户数据录入
创建录入界面,获取用户输入后插入数据库:
saveButton.setOnClickListener(v -> { String name = nameEditText.getText().toString().trim(); String category = categoryEditText.getText().toString().trim(); float servingSize = Float.parseFloat(servingSizeEditText.getText().toString()); float totalCaffeine = Float.parseFloat(totalCaffeineEditText.getText().toString()); float per100ml = totalCaffeine / servingSize * 100; // 自动计算每100ml含量 Drink newDrink = new Drink(name, category, servingSize, totalCaffeine, per100ml); new Thread(() -> { db.drinkDao().insertDrink(newDrink); runOnUiThread(() -> { Toast.makeText(this, "数据已保存", Toast.LENGTH_SHORT).show(); finish(); }); }).start(); });
四、新手注意事项
- 所有数据库操作必须在子线程执行,避免阻塞主线程;也可使用Room结合Coroutines简化线程处理
- 实体类字段名需与Dao查询语句中的列名一致,或用
@ColumnInfo指定别名 - 测试阶段可临时添加
allowMainThreadQueries()允许主线程操作,但正式发布必须移除 - 后续数据库版本升级需编写迁移逻辑,防止数据丢失
内容的提问来源于stack exchange,提问作者Kief
相关产品推荐
相关产品推荐

