質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

2758閲覧

Cursorオブジェクトについて

Kuukai64

総合スコア9

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2020/04/14 18:37

Android Studioを用いてアプリ開発の勉強をしている学生です。

使用言語はKotolinです。

以下にコード一式(MainActivity.kt, DatabaseHelper.kt, activity_main.xml, strings.xmlの順)を添付しております。

SQLiteを用いてデータベースから特定の行・特定の列の値を表示させるコードの記述がMainActivity.ktのListItemClickListenerクラスのonItemClickメソッド内にあります。

ここではrawQueryメソッドでCursorオブジェクトを取得していますが、そのCursorオブジェクトについて質問があります。

質問1.
SQLiteのSELECTにおいて、WHERE句の条件式で_idを指定し、その一行だけをCursorオブジェクトとして表示しているはずなのにその後while文でCursor内を一行ずつループさせてデータを取得しようとしている理由が分かりません。
そもそも私のCursorに対する認識が間違っているのでしょうか。

質問2.
Cursorオブジェクトの0行目というのは、カラム名がある行(今回でいえば _id, name, note が書いてある一番上の行)を指しているのでしょうか。

Kotolin

1package com.websarva.wings.android.databesesample 2 3import androidx.appcompat.app.AppCompatActivity 4import android.os.Bundle 5import android.view.View 6import android.widget.* 7 8class MainActivity : AppCompatActivity() { 9 //カクテルリストビューのインデックス番号とカクテル名の初期化 10 private var _cocktailId = -1 11 private var _cocktailName = "" 12 13 //データベースヘルパーオブジェクト生成 14 private val _helper = DatabaseHelper(this@MainActivity) 15 16 //最初に行われる処理 17 override fun onCreate(savedInstanceState: Bundle?) { 18 super.onCreate(savedInstanceState) 19 setContentView(R.layout.activity_main) 20 21 //カクテルリストビューにリスナクラスを設定 22 val lvCocktail = findViewById<ListView>(R.id.lvCocktail) 23 lvCocktail.onItemClickListener = ListItemClickListener() 24 } 25 26 //保存ボタンがタップされた時の処理 27 fun onSaveButtonClick(view: View){ 28 //入力された感想を取得 29 val etNote = findViewById<EditText>(R.id.etNote) 30 val note = etNote.text.toString() 31 32 //データベースヘルパーオブジェクトからデータベース接続オブジェクトを取得 33 val db = _helper.writableDatabase 34 //メモデータを削除、インサートの順にSQLを実行する 35 //削除用SQL文字列を作成 36 val sqlDelete = "DELETE FROM cocktailmemos WHERE _id = ?" 37 //SQL文字列をもとにプリペアードステートメントを取得 38 var stmt = db.compileStatement(sqlDelete) 39 //変数のバインド 40 stmt.bindLong(1, _cocktailId.toLong()) 41 //削除SQLの実行 42 stmt.executeUpdateDelete() 43 //インサート用SQL文字列の生成 44 val sqlInsert = "INSERT INTO cocktailmemos(_id, name, note) VALUES (?, ?, ?)" 45 //SQL文字列をもとにプリペアードステートメントを取得 46 stmt = db.compileStatement(sqlInsert) 47 //変数のバインド 48 stmt.bindLong(1, _cocktailId.toLong()) 49 stmt.bindString(2, _cocktailName) 50 stmt.bindString(3, note) 51 //インサートSQLの実行 52 stmt.executeInsert() 53 54 55 //感想欄の入力欄を消去 56 etNote.setText("") 57 58 val tvCocktailName = findViewById<TextView>(R.id.tvCocktailName) 59 tvCocktailName.text = getString(R.string.tv_name) 60 61 val btnSave = findViewById<Button>(R.id.btnSave) 62 btnSave.isEnabled = false 63 } 64 65 //カクテル名がタップされた時のリスナクラス 66 private inner class ListItemClickListener: AdapterView.OnItemClickListener{ 67 override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) { 68 //カクテルリストビューのインデックス番号とカクテル名を取得 69 _cocktailId = position 70 _cocktailName = parent.getItemAtPosition(position) as String 71 72 //カクテル名表示欄にタップされたカクテル名を代入 73 val tvCocktailName = findViewById<TextView>(R.id.tvCocktailName) 74 tvCocktailName.text = _cocktailName 75 76 //保存ボタンをタップ可能にする処理 77 val btnSave = findViewById<Button>(R.id.btnSave) 78 btnSave.isEnabled = true 79 80 //カクテルリストをタップした時にすでにデータが存在した場合には、その内容を表示する 81 //データベースヘルパーオブジェクトからデータベース接続オブジェクトを取得 82 val db = _helper.writableDatabase 83 //主キーによる検索SQL文字列の用意 84 val sql = "SELECT * FROM cocktailmemos WHERE _id = ${_cocktailId}" 85 //SQLの実行 86 val cursor = db.rawQuery(sql, null) 87 //データベースから取得した値を格納するための変数の用意 88 var note = "" 89 //SQL実行の戻り値であるカーソルオブジェクトをループさせてデータベース内のデータを取得 90 while(cursor.moveToNext()){ 91 //カラムのインデックス値を取得 92 val idxNote = cursor.getColumnIndex("note") 93 //カラムのインデックス値をもとに実際のデータを取得 94 note = cursor.getString(idxNote) 95 96 } 97 //感想のEditTextの画面部品を取得しデータベースの値を反映 98 val etNote = findViewById<EditText>(R.id.etNote) 99 etNote.setText(note) 100 } 101 } 102 103 //データベースヘルパークラスの解放 104 override fun onDestroy() { 105 _helper.close() 106 super.onDestroy() 107 } 108} 109

Kotolin

1package com.websarva.wings.android.databesesample 2 3import android.content.Context 4import android.database.sqlite.SQLiteDatabase 5import android.database.sqlite.SQLiteOpenHelper 6 7class DatabaseHelper(context: Context): SQLiteOpenHelper(context, DATABASE_NAME, null, DATEBASE_VERSION) { 8 9 companion object{ 10 private const val DATABASE_NAME = "cocktailmemo.db" 11 private const val DATEBASE_VERSION = 1 12 } 13 14 override fun onCreate(db: SQLiteDatabase) { 15 //テーブル作成用SQL文字列の生成 16 val sb = StringBuilder() 17 sb.append("CREATE TABLE cocktailmemos (") 18 sb.append("_id INTEGER PRIMARY KEY,") 19 sb.append("name TEXT,") 20 sb.append("note TEXT") 21 sb.append(");") 22 val sql = sb.toString() 23 24 //SQLの実行 25 db.execSQL(sql) 26 } 27 28 override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) { 29 } 30}

xml

1<?xml version="1.0" encoding="utf-8"?> 2<LinearLayout 3 xmlns:android ="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:orientation="vertical"> 7 8 <ListView 9 android:id="@+id/lvCocktail" 10 android:layout_width="match_parent" 11 android:layout_height="0dp" 12 android:layout_marginBottom="10dp" 13 android:layout_weight="0.6" 14 android:entries="@array/lv_cocktaillist"/> 15 16 <TextView 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:text="@string/tv_lb_name" 20 android:textSize="20sp"/> 21 22 <TextView 23 android:id="@+id/tvCocktailName" 24 android:layout_width="wrap_content" 25 android:layout_height="wrap_content" 26 android:text="@string/tv_name" 27 android:textSize="20sp"/> 28 29 <TextView 30 android:layout_width="wrap_content" 31 android:layout_height="wrap_content" 32 android:layout_marginTop="5dp" 33 android:text="@string/tv_lb_note" 34 android:textSize="20sp"/> 35 36 <EditText 37 android:id="@+id/etNote" 38 android:layout_width="match_parent" 39 android:layout_height="0dp" 40 android:layout_weight="0.4" 41 android:gravity="top" 42 android:inputType="textMultiLine"/> 43 44 <Button 45 android:id="@+id/btnSave" 46 android:layout_width="match_parent" 47 android:layout_height="wrap_content" 48 android:enabled="false" 49 android:onClick="onSaveButtonClick" 50 android:text="@string/btn_save" /> 51</LinearLayout>

XML

1<resources> 2 <string name="app_name">データベースサンプル</string> 3 <string-array name="lv_cocktaillist"> 4 <item>ホワイトレディ</item> 5 <item>バラライカ</item> 6 <item>XYZ</item> 7 <item>ニューヨーク</item> 8 <item>マンハッタン</item> 9 <item>ミシシッピミュール</item> 10 <item>ブルーハワイ</item> 11 </string-array> 12 <string name="tv_lb_name">選択されたカクテル</string> 13 <string name="tv_name">未選択</string> 14 <string name="tv_lb_note">感想</string> 15 <string name="btn_save">保存</string> 16</resources> 17

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2020/04/14 19:08

一応, "kotlin" です.
guest

回答1

0

ベストアンサー

while文でCursor内を一行ずつループ

その SELECT 文で読めるのは 0 行 か 1 行だけなのであれば, ループしてもしなくても結果は同じですので, while か if かという違いだけで問題はありません.
どちらかというと _id を position としていることや, SQL を直接編集していること, SELECT * を使っていること等などが気になります.

Cursorオブジェクトの0行目

0行目などありましたでしょうか.

投稿2020/04/14 19:05

jimbe

総合スコア12646

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2020/04/14 19:09

> 0行目などありましたでしょうか. 単にインデックスが0始まりというだけの話である気がします。
Kuukai64

2020/04/15 02:12

これらのコードは書籍のサンプルプログラムなのですが、その書籍の解説では「はじめ、カーソル内では0行目に位置しています」と記述されていました。 今回のプログラムでは、SELECTの際に_idを指定しているので返されるカーソルは1行のはずなのです。 ですが、その後のwhile文ではmoveToNextメソッドが使用されています。 これだと、0行目(返されるカーソル1行)の次の行を調べてmoveToNextメソッドはFalseを返すのではないかという疑問があります。 このような意図で質問をさせていただいております。
jimbe

2020/04/15 03:57

> インデックスが0始まり そういえば行も 0 からでした. カラムはともかく行は精々 moveToFirst ぐらいなので忘れてました(_ _
Kuukai64

2020/04/15 06:41

書籍で「はじめ、カーソル内では0行目に位置しています」という記述がされていたために混乱してしまいましたが、実は存在しない-1行目に位置していて、moveToNext()によってデータのあるであろう0行目にカーソルが移動しTrueをwhile文に返していた、という解釈で納得することが出来ました。 moveToFirst()は普通に0行目にカーソルが移動するという理解で間違いないかと思います。 書籍では誤解を招く表現や誤植が存在する場合がありますが、APIリファレンスを参照すると間違い無いでしょうから、これからは不明点が出てきた場合にはなるべくリファレンスを調べてみようと思います。 素人の私に何度も回答していただき有難うございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問