実現したいこと
Android Studioでクイズアプリを作成しており、SQliteで問題データを保存しています。
問題を間違えた際にその日付を文字列型として保存する処理までは作成できたのですが、
保存された日付と今日の日付を比較し、1日以上前のレコードだけを抜き出して配列に格納して画面に表示するという処理を実現したいです。
前提
ReviewActivity.javaの中でクイズ配列(quizArray)を作成し、QuizDatabase.java内の 'getRecordsOlderThanOneDay' メソッドを呼び出しています。メソッドから受け取ったCursorオブジェクトからデータを取り出し、クイズ配列に格納しています。
その後、クイズ配列内の問題文、正解、選択肢、解説を取り出して表示するという処理を行っています。
'getRecordsOlderThanOneDay' メソッドでは、今日から1日以上前の日付を文字列型の変数oneDayAgoに代入し、データベース内の日付とData型で比較、条件に合うレコードだけを戻り値Cursorとして渡しています。
説明が分かりにくかったらすみません。
発生している問題
保存されている日付が1日以上前の問題データだけを抜き出してクイズ配列に格納したいのですが、すべてのレコードが格納されてしまいます。
該当のソースコード
文字数制限のため、xmlとimportは省略しています。
ReviewActivity.java
java
1package com.example.testapp; 2 3public class ReviewActivity extends AppCompatActivity implements View.OnClickListener { 4 5 private TextView review_countLabel, questionLabel; 6 private Button answerBtn1, answerBtn2, answerBtn3, answerBtn4; 7 8 private String rightAnswer; 9 private String kaisetu; 10 private int rightAnswerCount; // 正解数 11 private int quizCount = 1; 12 static final private int QUIZ_COUNT = 3; // 問題の出題数 13 14 ArrayList<ArrayList<String>> quizArray = new ArrayList<>(); 15 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 super.onCreate(savedInstanceState); 19 setContentView(R.layout.activity_review); 20 21 review_countLabel = findViewById(R.id.review_countLabel); 22 questionLabel = findViewById(R.id.questionLabel); 23 answerBtn1 = findViewById(R.id.answerBtn1); 24 answerBtn2 = findViewById(R.id.answerBtn2); 25 answerBtn3 = findViewById(R.id.answerBtn3); 26 answerBtn4 = findViewById(R.id.answerBtn4); 27 28 answerBtn1.setOnClickListener(this); 29 answerBtn2.setOnClickListener(this); 30 answerBtn3.setOnClickListener(this); 31 answerBtn4.setOnClickListener(this); 32 33 QuizDatabase dbHelper = new QuizDatabase(this); 34 SQLiteDatabase db = dbHelper.getWritableDatabase(); 35 36 try { 37 // getRecordsOlderThanOneDay メソッドを呼び出して1日以上前のレコードを取得 38 Cursor cursor2 = dbHelper.getRecordsOlderThanOneDay(); 39 40 // quizArrayを作成 41 // tmpArrayでクイズを1問ずつ作成してquizArrayにセット 42 // 文字列型のgetString()で取り出す 43 while (cursor2.moveToNext()) { 44 ArrayList<String> tmpArray = new ArrayList<>(); 45 tmpArray.add(cursor2.getString(0)); // 問題 46 tmpArray.add(cursor2.getString(1)); // 正解 47 tmpArray.add(cursor2.getString(2)); // 選択肢1 48 tmpArray.add(cursor2.getString(3)); // 選択肢2 49 tmpArray.add(cursor2.getString(4)); // 選択肢3 50 tmpArray.add(cursor2.getString(6)); // 解説 51 quizArray.add(tmpArray); 52 } 53 54 // Cursorを閉じる 55 cursor2.close(); 56 } finally { 57 // データベースを閉じる 58 db.close(); 59 } 60 61 } 62 63 public void showNextQuiz() { 64 // クイズカウントラベルを更新 65 review_countLabel.setText(getString(R.string.review_countLabel, quizCount)); 66 67 // ランダムな数字を取得 68 Random random = new Random(); 69 int randomNum = random.nextInt(quizArray.size()); 70 71 // randomNumを使って、quizArrayからクイズを一つ取り出す 72 ArrayList<String> quiz = quizArray.get(randomNum); 73 74 // 問題文を表示 75 questionLabel.setText(quiz.get(0)); 76 77 // 正解と解説をrightAnswerにセット 78 rightAnswer = quiz.get(1); 79 kaisetu = quiz.get(5); 80 81 // 正解と選択肢3つをシャッフル 82 Collections.shuffle(quiz); 83 84 // 解答ボタンに正解と選択肢3つを表示 85 answerBtn1.setText(quiz.get(0)); 86 answerBtn2.setText(quiz.get(1)); 87 answerBtn3.setText(quiz.get(2)); 88 answerBtn4.setText(quiz.get(3)); 89 90 // このクイズをquizArrayから削除 91 quizArray.remove(randomNum); 92 } 93 94 @Override 95 public void onClick(View view) { 96 97 // どの解答ボタンが押されたか 98 Button answerBtn = findViewById(view.getId()); 99 String btnText = answerBtn.getText().toString(); 100 101 String alertTitle; 102 if (btnText.equals(rightAnswer)) { 103 alertTitle = "正解"; 104 rightAnswerCount++; 105 } else { 106 alertTitle = "不正解"; 107 //日付カラムを更新 QuizDatabaseからメソッドを呼び出す 108 QuizDatabase dbHelper = new QuizDatabase(this); 109 dbHelper.updatedaydateColumn(questionLabel.getText().toString()); 110 } 111 112 //ダイアログオブジェクトを作成 113 DialogFragment dialogFragment = new AnswerDialogFragment(); 114 115 //ダイアログに「正解・解説文」を渡す 116 Bundle args = new Bundle(); 117 args.putString("alertTitle", alertTitle); //putString(キー,値) 118 args.putString("rightAnswer", rightAnswer); 119 args.putString("btnText", btnText); 120 args.putString("kaisetu", kaisetu); 121 dialogFragment.setArguments(args); 122 123 //ダイアログが閉じないようにする 124 dialogFragment.setCancelable(false); 125 126 //ダイアログの表示 127 dialogFragment.show(getSupportFragmentManager(), "answer_dialog"); 128 } 129}
QuizDatabase.java
java
1package com.example.testapp; 2 3public class QuizDatabase extends SQLiteOpenHelper { 4 5 static final private String DBNAME = "testapp.sqlite"; 6 static final private int VERSION = 5; 7 //データベースのバージョン番号(データベース書き換えのたびに更新) 8 9 String[][] quizData = { 10 //{"問題", "正解", "選択肢1", "選択肢2", "選択肢3", "カテゴリ", "解説", 間違えた日付} 11 {"基礎理論 問題1", "1", "2", "3", "4", "1", "解説(仮)","2023-12-14"}, 12 {"基礎理論 問題2", "1", "2", "3", "4", "1", "解説(仮)","2023-12-14"}, 13 {"基礎理論 問題3", "1", "2", "3", "4", "1", "解説(仮)","2023-12-14"}, 14 {"基礎理論 問題4", "1", "2", "3", "4", "1", "解説(仮)","0"}, 15 {"基礎理論 問題5", "1", "2", "3", "4", "1", "解説(仮)","0"}, 16 {"コンピュータシステム 問題6", "1", "2", "3", "4", "2", "解説(仮)","0"}, 17 {"コンピュータシステム 問題7", "1", "2", "3", "4", "2", "解説(仮)","0"}, 18 {"コンピュータシステム 問題8", "1", "2", "3", "4", "2", "解説(仮)","0"}, 19 {"コンピュータシステム 問題9", "1", "2", "3", "4", "2", "解説(仮)","0"}, 20 {"コンピュータシステム 問題10", "1", "2", "3", "4", "2", "解説(仮)","0"}, 21 }; 22 23 public QuizDatabase(Context context) { 24 super(context, DBNAME, null, VERSION); 25 } 26 27 28 @Override 29 public void onCreate(SQLiteDatabase db) { 30 //クイズデータのテーブルを作成 31 db.execSQL("CREATE TABLE quiz (" + 32 "question TEXT PRIMARY KEY, answer TEXT, choice1 TEXT," + 33 "choice2 TEXT, choice3 TEXT, category TEXT, kaisetu TEXT, daydate TEXT)"); 34 35 //トランザクションの開始(クイズデータの登録) 36 db.beginTransaction(); 37 try{ 38 SQLiteStatement sql = db.compileStatement( 39 "INSERT INTO quiz (question, answer, choice1, choice2, choice3, category, kaisetu, daydate)" + 40 "VALUES(?, ?, ?, ?, ?, ?, ?, ?)" 41 ); 42 43 // クイズデータを1行ずつ追加する 44 for (int i = 0; i < quizData.length; i++) { 45 // Valueをセット 46 // bindString(index, value)でプレースホルダー(?)に値を渡す 47 sql.bindString(1, quizData[i][0]); // 問題 48 sql.bindString(2, quizData[i][1]); // 正解 49 sql.bindString(3, quizData[i][2]); // 選択肢1 50 sql.bindString(4, quizData[i][3]); // 選択肢2 51 sql.bindString(5, quizData[i][4]); // 選択肢3 52 sql.bindString(6, quizData[i][5]); // カテゴリ 53 sql.bindString(7, quizData[i][6]); // 解説 54 sql.bindString(8, quizData[i][7]); // 日付 55 56 sql.executeInsert(); 57 } 58 59 //成功フラグ 60 db.setTransactionSuccessful(); 61 } 62 63 catch (SQLiteException e) { 64 //失敗 65 e.printStackTrace(); 66 } 67 68 finally { 69 //成功フラグあり→トランザクション終了、成功フラグなし→ロールバック 70 db.endTransaction(); 71 } 72 } 73 74 @Override 75 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 76 if(oldVersion < newVersion) { //新しいバージョンがあるか判定 77 db.execSQL("DROP TABLE IF EXISTS quiz"); //今のquizテーブルをDROP 78 onCreate(db); //再度quizテーブルを作成 79 } 80 } 81 82 //今日の日付を指定のカラムに書き込むメソッド 83 public void updatedaydateColumn(String question) { 84 SQLiteDatabase db = this.getWritableDatabase(); 85 ContentValues values = new ContentValues(); 86 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 87 String todayDate = sdf.format(Calendar.getInstance().getTime()); 88 89 values.put("daydate", todayDate); 90 91 // 第一引数がテーブル名、第二引数が更新するデータ、第三引数がWHERE句 92 db.update("quiz", values, "question=?", new String[]{question}); 93 db.close(); 94 } 95 96 // 日付が1日以上前のレコードを取得するメソッド 97 public Cursor getRecordsOlderThanOneDay() { 98 SQLiteDatabase db = this.getReadableDatabase(); 99 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); 100 101 // 現在の日付から1日前の日付を計算 102 Calendar calendar = Calendar.getInstance(); 103 calendar.add(Calendar.DAY_OF_MONTH, -1); 104 String oneDayAgo = sdf.format(calendar.getTime()); 105 106 // クエリを実行して該当するレコードを取得 107 Cursor cursor = db.query( 108 "quiz", 109 null, // 全てのカラムを取得 110 "date(daydate) <= date(?)", 111 new String[]{oneDayAgo}, 112 null, 113 null, 114 null 115 ); 116 117 return cursor; 118 } 119} 120
補足情報(FW/ツールのバージョンなど)
Android Studio Flamingo
qiitaでも同様に質問済です。
https://qiita.com/daaaa1002/questions/e84899ffd10c27223f46
回答1件
あなたの回答
tips
プレビュー