Android开发求助:动态列数据库表的AddScoreActivity实现咨询
嗨,看起来你已经搭好了应用的核心框架,接下来要实现分数录入功能对吧?我来一步步给你梳理实现思路和关键代码,帮你搞定AddScoreActivity:
核心思路梳理
因为table2的列数和table1的人名数量完全对应,所以实现逻辑可以拆成这几步:
- 从
table1拉取所有人员名单 - 根据名单动态生成对应的分数录入控件
- 校验用户输入的分数合法性
- 将分数批量保存/更新到
table2
第一步:完善DBHelper的工具方法
首先要给你的DBHelper类补充几个关键方法,用来获取人员名单、同步table2的列结构:
1. 获取所有人员名单
public List<String> getAllPersons() { List<String> persons = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT name FROM table1", null); if (cursor.moveToFirst()) { do { persons.add(cursor.getString(0)); } while (cursor.moveToNext()); } cursor.close(); db.close(); return persons; }
2. 同步table2的列(新增人员时调用)
因为table2的列要和table1的人名一一对应,所以每次在AddPersonActivity添加人员后,需要给table2新增对应列:
public void syncTable2Column(String newPersonName) { SQLiteDatabase db = this.getWritableDatabase(); try { // 先检查table2是否存在 Cursor tableCursor = db.rawQuery( "SELECT name FROM sqlite_master WHERE type='table' AND name='table2'", null ); boolean tableExists = tableCursor.moveToFirst(); tableCursor.close(); if (!tableExists) { // 首次添加人员时创建table2并初始化第一列 db.execSQL("CREATE TABLE table2 (" + newPersonName + " INTEGER DEFAULT 0)"); } else { // 检查列是否已存在,避免重复添加 Cursor columnCursor = db.rawQuery("PRAGMA table_info(table2)", null); boolean columnExists = false; if (columnCursor.moveToFirst()) { do { String existingCol = columnCursor.getString(columnCursor.getColumnIndex("name")); if (existingCol.equals(newPersonName)) { columnExists = true; break; } } while (columnCursor.moveToNext()); } columnCursor.close(); if (!columnExists) { db.execSQL("ALTER TABLE table2 ADD COLUMN " + newPersonName + " INTEGER DEFAULT 0"); } } } catch (SQLException e) { e.printStackTrace(); } finally { db.close(); } }
记得在AddPersonActivity添加人员成功后调用这个方法:
if (dbHelper.addPerson(newPersonName)) { dbHelper.syncTable2Column(newPersonName); Toast.makeText(this, "人员添加成功", Toast.LENGTH_SHORT).show(); finish(); }
第二步:实现AddScoreActivity
1. 布局文件(activity_add_score.xml)
用滚动布局适配多人员场景,动态生成的录入控件放在容器里:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <ScrollView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <LinearLayout android:id="@+id/ll_score_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:gap="12dp"/> </ScrollView> <Button android:id="@+id/btn_save_scores" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="保存所有分数"/> </LinearLayout>
2. Activity逻辑代码
public class AddScoreActivity extends AppCompatActivity { private DBHelper dbHelper; private LinearLayout scoreContainer; private List<String> personList; private List<EditText> scoreInputList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add_score); dbHelper = new DBHelper(this); scoreContainer = findViewById(R.id.ll_score_container); Button saveBtn = findViewById(R.id.btn_save_scores); // 获取人员名单 personList = dbHelper.getAllPersons(); if (personList.isEmpty()) { Toast.makeText(this, "暂无人员,请先添加", Toast.LENGTH_SHORT).show(); saveBtn.setEnabled(false); return; } // 动态生成录入控件 generateScoreInputs(); // 保存按钮点击事件 saveBtn.setOnClickListener(v -> saveScoresToDB()); } private void generateScoreInputs() { for (String person : personList) { // 每行布局:人名 + 分数输入框 LinearLayout rowLayout = new LinearLayout(this); rowLayout.setOrientation(LinearLayout.HORIZONTAL); rowLayout.setGravity(Gravity.CENTER_VERTICAL); rowLayout.setGap(8dp); // 人名文本 TextView personTv = new TextView(this); personTv.setText(person); personTv.setLayoutParams(new LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f )); // 分数输入框(限制整数输入) EditText scoreEt = new EditText(this); scoreEt.setHint("输入分数"); scoreEt.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_SIGNED); scoreEt.setLayoutParams(new LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f )); scoreInputList.add(scoreEt); rowLayout.addView(personTv); rowLayout.addView(scoreEt); scoreContainer.addView(rowLayout); } } private void saveScoresToDB() { // 收集并校验分数 List<Integer> scores = new ArrayList<>(); boolean isInputValid = true; for (EditText et : scoreInputList) { String scoreStr = et.getText().toString().trim(); if (scoreStr.isEmpty()) { Toast.makeText(this, "请填写所有分数", Toast.LENGTH_SHORT).show(); isInputValid = false; break; } try { scores.add(Integer.parseInt(scoreStr)); } catch (NumberFormatException e) { Toast.makeText(this, "请输入有效的整数分数", Toast.LENGTH_SHORT).show(); isInputValid = false; break; } } if (!isInputValid) return; // 批量保存到table2(用事务保证数据一致性) SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransaction(); try { ContentValues values = new ContentValues(); for (int i = 0; i < personList.size(); i++) { values.put(personList.get(i), scores.get(i)); } // 判断table2是否已有数据,有则更新,无则插入 Cursor cursor = db.rawQuery("SELECT * FROM table2 LIMIT 1", null); if (cursor.moveToFirst()) { db.update("table2", values, null, null); } else { db.insert("table2", null, values); } cursor.close(); db.setTransactionSuccessful(); Toast.makeText(this, "分数保存成功", Toast.LENGTH_SHORT).show(); finish(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, "保存失败,请重试", Toast.LENGTH_SHORT).show(); } finally { db.endTransaction(); db.close(); } } @Override protected void onDestroy() { super.onDestroy(); if (dbHelper != null) { dbHelper.close(); } } }
关键注意事项
- 输入校验:通过
InputType限制输入为整数,同时在保存时捕获格式异常,避免崩溃 - 事务处理:批量操作数据库时用事务,防止部分数据保存失败导致的不一致
- 动态列同步:一定要保证
table2的列和table1的人名完全同步,否则会出现保存失败的情况 - 空状态处理:当
table1没有人员时,禁用保存按钮并提示用户先添加人员
内容的提问来源于stack exchange,提问作者Mohammad Reza Norasideh
相关产品推荐
相关产品推荐

