Android健身房训练APP开发:SimpleCursorAdapter与一对多数据存储技术问询
嘿,我来帮你梳理下这个健身房训练追踪App的功能实现思路,结合你已经有的数据库助手类和训练查看Activity,咱们一步步拆解来做:
第一步:确认/调整数据库表结构
要实现训练项目和练习的一对多关联,咱们需要两张关联的表:
- 训练表(比如命名为
workouts):你已经有_id主键,再加上存储训练名称的workout_name字段就够了 - 练习表(比如命名为
exercises):除了_id主键和存储练习名称的exercise_name,还得加一个workout_id外键,用来关联对应训练项目的_id
在你的数据库助手类(DBHelper)里,更新onCreate方法的建表语句:
@Override public void onCreate(SQLiteDatabase db) { // 开启外键约束,保证关联数据的完整性 db.execSQL("PRAGMA foreign_keys = ON;"); // 创建训练表 db.execSQL("CREATE TABLE workouts (_id INTEGER PRIMARY KEY AUTOINCREMENT, workout_name TEXT NOT NULL);"); // 创建练习表,通过workout_id关联训练表 db.execSQL("CREATE TABLE exercises (_id INTEGER PRIMARY KEY AUTOINCREMENT, exercise_name TEXT NOT NULL, workout_id INTEGER NOT NULL, FOREIGN KEY(workout_id) REFERENCES workouts(_id));"); }
第二步:添加练习Activity的核心实现
首先,用户在命名训练项目后,你需要先把训练名称插入训练表,拿到对应的_id,再通过Intent把这个ID传递到添加练习的Activity里——这是关联训练和练习的关键。
2.1 接收训练ID并初始化ListView
在添加练习的Activity的onCreate方法里,先获取传递过来的训练ID,然后用SimpleCursorAdapter初始化ListView:
// 获取从训练命名界面传递来的训练ID long workoutId = getIntent().getLongExtra("EXTRA_WORKOUT_ID", -1); if (workoutId == -1) { // 如果没拿到有效ID,直接返回上一页 finish(); return; } // 初始化数据库连接和Cursor DBHelper dbHelper = new DBHelper(this); SQLiteDatabase db = dbHelper.getReadableDatabase(); // 查询当前训练下的所有练习,用来填充ListView Cursor exerciseCursor = db.query( "exercises", new String[]{"_id", "exercise_name"}, // 只查需要的列 "workout_id = ?", // 过滤条件:只属于当前训练的练习 new String[]{String.valueOf(workoutId)}, null, null, null ); // 设置SimpleCursorAdapter SimpleCursorAdapter adapter = new SimpleCursorAdapter( this, android.R.layout.simple_list_item_1, // 用系统默认的列表项布局,也可以自定义 exerciseCursor, new String[]{"exercise_name"}, // Cursor里对应的列名 new int[]{android.R.id.text1}, // 布局里用来显示练习名称的TextView ID 0 ); ListView exerciseListView = findViewById(R.id.list_exercises); exerciseListView.setAdapter(adapter);
2.2 实现添加练习的功能
假设你的布局里有输入练习名称的EditText(id: et_exercise_name)和添加按钮(id: btn_add_exercise),给按钮加点击事件:
EditText etExerciseName = findViewById(R.id.et_exercise_name); Button btnAddExercise = findViewById(R.id.btn_add_exercise); btnAddExercise.setOnClickListener(v -> { String exerciseName = etExerciseName.getText().toString().trim(); if (!exerciseName.isEmpty()) { // 准备要插入练习的数据 ContentValues values = new ContentValues(); values.put("exercise_name", exerciseName); values.put("workout_id", workoutId); // 关联当前训练ID // 插入到数据库 db.insert("exercises", null, values); // 刷新Cursor和Adapter,让新添加的练习立刻显示在ListView上 Cursor newCursor = db.query( "exercises", new String[]{"_id", "exercise_name"}, "workout_id = ?", new String[]{String.valueOf(workoutId)}, null, null, null ); adapter.swapCursor(newCursor); // 清空输入框,方便继续添加 etExerciseName.setText(""); } });
2.3 完成按钮的逻辑
当用户点击完成按钮时,只需关闭当前Activity,回到训练查看界面即可——如果需要通知训练查看界面刷新数据,可以设置返回结果:
Button btnFinish = findViewById(R.id.btn_finish); btnFinish.setOnClickListener(v -> { // 设置返回结果,让训练查看界面知道可以刷新数据 setResult(RESULT_OK); finish(); });
第三步:训练查看Activity的关联展示
在训练查看界面,当用户选中某个训练项目时,你需要查询该训练下的所有练习,同样用SimpleCursorAdapter展示:
// 假设当前选中的训练ID是selectedWorkoutId Cursor exerciseCursor = db.query( "exercises", new String[]{"_id", "exercise_name"}, "workout_id = ?", new String[]{String.valueOf(selectedWorkoutId)}, null, null, null ); SimpleCursorAdapter exerciseAdapter = new SimpleCursorAdapter( this, android.R.layout.simple_list_item_1, exerciseCursor, new String[]{"exercise_name"}, new int[]{android.R.id.text1}, 0 ); ListView workoutExerciseList = findViewById(R.id.list_workout_exercises); workoutExerciseList.setAdapter(exerciseAdapter);
几个关键注意事项
- 记得管理Cursor和数据库连接:在Activity的
onDestroy方法里关闭Cursor和数据库,避免内存泄漏;更推荐用CursorLoader来管理Cursor,它会自动处理生命周期,数据变化时自动刷新。 - 输入验证:一定要检查用户输入的训练名称、练习名称是否为空,避免插入无效数据。
- 级联操作(可选):如果需要删除训练时自动删除对应的所有练习,可以在建练习表时添加
ON DELETE CASCADE,比如把练习表的建表语句改成:db.execSQL("CREATE TABLE exercises (_id INTEGER PRIMARY KEY AUTOINCREMENT, exercise_name TEXT NOT NULL, workout_id INTEGER NOT NULL, FOREIGN KEY(workout_id) REFERENCES workouts(_id) ON DELETE CASCADE);");
内容的提问来源于stack exchange,提问作者user303749
相关产品推荐
相关产品推荐

