[Android Studio] メモ帳を作ろう!(その3)[Kotlin]

どうも、tatsuです!

今回はメモ帳アプリ制作その3ということで作っていこうと思います。
わからない箇所は他の記事を参考にしてみてください。

※この記事で使用しているAndroid Studioのバージョンは3.1.4です。

作成手順

メモ帳アプリを作る上で必要な手順を以下にまとめました。
本記事では④を紹介します。
①②③は以下の記事を参照してください。

[Android Studio] メモ帳を作ろう!(その2)[Kotlin]

2018.11.26

[Android Studio] メモ帳を作ろう!(その1)[Kotlin]

2018.11.25
  1. 新しくプロジェクトを作る
  2. 画面レイアウトを作る
  3. 画面に動きをつける
  4. データベースに保存する
  5. テスト&手直し
  6. 完成物披露

④データベースに保存する

前回画面に動きをつけましたが、今回はそこで保留にしていたデータベース処理を作っていこうと思います!

OpenHelperクラスを作る

データベースといったらまずOpenHelperクラスを作りましょう。
OpenHelperクラスの詳しい作り方は[Android Studio] データベースにデータを保存するを参照してください。

今回はMemoOpenHelperというktクラスを作成しました。
MEMO_TABLEには連番で振られていくidとランダム文字列のuuid、最後にメモ本体のbodyを持たせています。

class MemoOpenHelper
// コンストラクタ 以下のように呼ぶこと
(context: Context) : SQLiteOpenHelper(context, DBName, null, VERSION) {

    // データベースが作成された時に実行される処理
    // データベースはアプリを開いた時に存在しなかったら作成され、すでに存在していれば何もしない
    override fun onCreate(db: SQLiteDatabase) {
        /**
         * テーブルを作成する
         * execSQLメソッドにCREATET TABLE命令を文字列として渡すことで実行される
         * 引数で指定されているものの意味は以下の通り
         * 引数1 ・・・ id:列名 , INTEGER:数値型 , PRIMATY KEY:テーブル内の行で重複無し , AUTOINCREMENT:1から順番に振っていく
         * 引数2 ・・・ uuid:列名 , TEXT:文字列型
         * 引数3 ・・・ body:列名 , TEXT:文字列型
         */
        db.execSQL("CREATE TABLE MEMO_TABLE (" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                "uuid TEXT, " +
                "body TEXT)")

    }

    // データベースをバージョンアップした時に実行される処理
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        /**
         * テーブルを削除する
         */
        db.execSQL("DROP TABLE IF EXISTS MEMO_TABLE")

        // 新しくテーブルを作成する
        onCreate(db)
    }

    companion object {

        // データベース名
        private val DBName = "MEMO_DB"
        // データベースのバージョン(2,3と挙げていくとonUpgradeメソッドが実行される)
        private val VERSION = 1
    }

}

各アクティビティにデータベース処理を実装する

前回保留にしていたデータベースの処理を実装していきます。

ListActivity.kt

ListActivity.ktは以下の通りにします。
前回作成した仮データの部分はコメントアウトしてありますので、どこが変わったか確認してみてください。

class ListActivity : AppCompatActivity() {

    // MemoOpenHelperクラスを定義
    internal var helper: MemoOpenHelper? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_list)

        // データベースから値を取得する
        if (helper == null) {
            helper = MemoOpenHelper(this@ListActivity)
        }
        // メモリストデータを格納する変数
        val memoList = ArrayList<HashMap<String, String>>()
        // データベースを取得する
        val db = helper!!.writableDatabase
        try {
            // rawQueryというSELECT専用メソッドを使用してデータを取得する
            val c = db.rawQuery("select uuid, body from MEMO_TABLE order by id", null)
            // Cursorの先頭行があるかどうか確認
            var next = c.moveToFirst()

            // 取得した全ての行を取得
            while (next) {
                val data = HashMap<String, String>()
                // 取得したカラムの順番(0から始まる)と型を指定してデータを取得する
                val uuid = c.getString(0)
                var body = c.getString(1)
                if (body.length > 10) {
                    // リストに表示するのは10文字まで
                    body = body.substring(0, 11) + "..."
                }
                // 引数には、(名前,実際の値)という組合せで指定します 名前はSimpleAdapterの引数で使用します
                data["body"] = body
                data["id"] = uuid
                memoList.add(data)
                // 次の行が存在するか確認
                next = c.moveToNext()
            }
        } finally {
            // finallyは、tryの中で例外が発生した時でも必ず実行される
            // dbを開いたら確実にclose
            db.close()
        }

        /* 仮のデータを作成
        ArrayList<HashMap<String, String>> tmpList = new ArrayList<>();
        for(int i = 1; i <=  5; i++){
            HashMap<String,String> data = new HashMap<>();
            // 引数には、(名前,実際の値)という組合せで指定します 名前はSimpleAdapterの引数で使用します
            data.put("body","サンプルデータ"+i);
            data.put("id","sampleId"+i);
            tmpList.add(data);
        }*/

        // Adapter生成
        val simpleAdapter = SimpleAdapter(this,
                memoList, // 使用するデータ
                android.R.layout.simple_list_item_2, // 使用するレイアウト
                arrayOf("body", "id"), // どの項目を
                intArrayOf(android.R.id.text1, android.R.id.text2) // どのidの項目に入れるか
        )

        // idがmemoListのListViewを取得
        val listView = findViewById<View>(R.id.memoList) as ListView
        listView.adapter = simpleAdapter

        // リスト項目をクリックした時の処理
        listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
            /**
             * @param parent ListView
             * @param view 選択した項目
             * @param position 選択した項目の添え字
             * @param id 選択した項目のID
             */
            // インテント作成  第二引数にはパッケージ名からの指定で、遷移先クラスを指定
            val intent = Intent(this@ListActivity, com.android.tatsu.simplememo.CreateMemoActivity::class.java)

            // 選択されたビューを取得 TwoLineListItemを取得した後、text2の値を取得する
            val two = view as TwoLineListItem
            //                TextView idTextView = (TextView)two.findViewById(android.R.id.text2);
            val idTextView = two.text2 as TextView
            val isStr = idTextView.text as String
            // 値を引き渡す (識別名, 値)の順番で指定します
            intent.putExtra("id", isStr)
            // Activity起動
            startActivity(intent)
        }


        /**
         * 新規作成するボタン処理
         */
        // idがnewButtonのボタンを取得
        val newButton = findViewById<View>(R.id.newButton) as Button
        // clickイベント追加
        newButton.setOnClickListener {
            // CreateMemoActivityへ遷移
            val intent = Intent(this@ListActivity, com.android.tatsu.simplememo.CreateMemoActivity::class.java)
            intent.putExtra("id", "")
            startActivity(intent)
        }
    }
}

CreateMemoActivity.kt

CreateMemoActivity.ktは以下の通りにします。
新規作成の場合と編集の場合で処理が違うので気を付けてください。

class CreateMemoActivity : AppCompatActivity() {

    // MemoOpenHelperクラスを定義
    internal var helper: MemoOpenHelper? = null
    // 新規フラグ
    internal var newFlag = false
    // id
    internal var id = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_create_memo)

        // データベースから値を取得する
        if (helper == null) {
            helper = MemoOpenHelper(this@CreateMemoActivity)
        }


        // ListActivityからインテントを取得
        val intent = this.intent
        // 値を取得
        id = intent.getStringExtra("id")
        // 画面に表示
        if (id == "") {
            // 新規作成の場合
            newFlag = true
        } else {
            // 編集の場合 データベースから値を取得して表示
            // データベースを取得する
            val db = helper!!.writableDatabase
            try {
                // rawQueryというSELECT専用メソッドを使用してデータを取得する
                val c = db.rawQuery("select body from MEMO_TABLE where uuid = '$id'", null)
                // Cursorの先頭行があるかどうか確認
                var next = c.moveToFirst()
                // 取得した全ての行を取得
                while (next) {
                    // 取得したカラムの順番(0から始まる)と型を指定してデータを取得する
                    val dispBody = c.getString(0)
                    val body = findViewById<View>(R.id.body) as EditText
                    body.setText(dispBody, TextView.BufferType.NORMAL)
                    next = c.moveToNext()
                }
            } finally {
                // finallyは、tryの中で例外が発生した時でも必ず実行される
                // dbを開いたら確実にclose
                db.close()
            }
        }

        /**
         * 登録ボタン処理
         */
        // idがregisterのボタンを取得
        val registerButton = findViewById<View>(R.id.register) as Button
        // clickイベント追加
        registerButton.setOnClickListener {
            // 入力内容を取得する
            val body = findViewById<View>(R.id.body) as EditText
            val bodyStr = body.text.toString()

            // データベースに保存する
            val db = helper!!.writableDatabase
            try {
                if (newFlag) {
                    // 新規作成の場合
                    // 新しくuuidを発行する
                    id = UUID.randomUUID().toString()
                    // INSERT
                    db.execSQL("insert into MEMO_TABLE(uuid, body) VALUES('$id', '$bodyStr')")
                } else {
                    // UPDATE
                    db.execSQL("update MEMO_TABLE set body = '$bodyStr' where uuid = '$id'")
                }
            } finally {
                // finallyは、tryの中で例外が発生した時でも必ず実行される
                // dbを開いたら確実にclose
                db.close()
            }
            // 保存後に一覧へ戻る
            val intent = Intent(this@CreateMemoActivity, com.android.tatsu.simplememo.ListActivity::class.java)
            startActivity(intent)
        }


        /**
         * 戻るボタン処理
         */
        // idがbackのボタンを取得
        val backButton = findViewById<View>(R.id.back) as Button
        // clickイベント追加
        backButton.setOnClickListener {
            // 保存せずに一覧へ戻る
            finish()
        }
    }
}

まとめ

今回は「③データベースに保存する」を紹介しました!
テストして問題なければメモアプリの完成となります!
次回、テストと完成版の披露をします。では続きは次回にしていきます。

[Android Studio] メモ帳を作ろう!(その4)[Kotlin]

2018.11.28

[Android Studio] 実機でAndroidアプリを起動する

2018.08.15

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です