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

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

ただいまの
回答率

87.36%

Realmに保存したデータをListviewに表示したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 134

score 6

前提・実現したいこと

Realmを使ったシンプルなメモアプリを作ろうと考えております。
realmの使い方は分かるようになったのですが、保存したデータをListViewに表示したいと考えております。調べてもなかなか理解が出来ないので、ご教授頂ければ幸いです。
現在は、Listviewへ追加、削除は出来ます。

該当のソースコード

        val et_name : EditText = findViewById(R.id.et_name)
        val bt_add : Button = findViewById(R.id.bt_add)
        val bt_delete : Button = findViewById(R.id.bt_delete)
        val lv : ListView = findViewById(R.id.lv)

        val adapter = ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,
            mutableListOf())
        lv.adapter = adapter

        //Realmを使う時に必要
        val realm = Realm.getDefaultInstance()

        //bt_addを押すとet_nameに入力した内容をDBに保存とListViewに表示する処理を記載する
        bt_add.setOnClickListener {
            if ( et_name.text.toString().isEmpty()){
                AlertDialog.Builder(this)
                    .setTitle("未入力")
                    .setMessage("名前を入力して下さい")
                    .setPositiveButton("OK",null)
                    .show()//et_nameが未入力の場合、アラートダイアログで表示
            }else{
                realm.beginTransaction()//Realmのはじまり
                try {
                    val user = realm.createObject(user::class.java)
                    user.setName(et_name.text.toString())//DBに書き込み
                    et_name.text.clear()//DBに書き込みしたらEditTextの文字をクリアする
                    Toast.makeText(applicationContext,"登録しました",Toast.LENGTH_SHORT).show()//トーストで表示
                    realm.commitTransaction()
                    adapter.add(user.getName())//et_nameの内容をListViewに追加する
                }catch (e:RealmException){}
            }
        }

        //ListViewをタップするとアラートダイアログを表示して、削除するかしないか判断する
        //合わせてDBに登録されているデータも一緒に削除する
        lv.setOnItemClickListener { parent, view, position, id ->
            AlertDialog.Builder(this)
                .setTitle("削除しますか??")
                    //Yesを押下した時の処理
                    //タップされたところの名前を削除とDBの削除
                .setPositiveButton("Yes",DialogInterface.OnClickListener { dialog, which ->
                    adapter.remove(adapter.getItem(id.toInt()))
                    adapter.notifyDataSetChanged()
                    //ここからDBの削除の処理を記載する
                    //現時点でタップされたとこの名前のDB削除方法は分からない
                    realm.beginTransaction()
                    val delete = adapter.getItem(id.toInt())
                    realm.where(user::class.java)
                    et_name.text.clear()
                    //Toast.makeText(applicationContext,"削除しました",Toast.LENGTH_SHORT).show()
                    realm.commitTransaction()
                })
                .setNegativeButton("No",DialogInterface.OnClickListener { dialog, which ->
                    Toast.makeText(applicationContext,"キャンセルしました",Toast.LENGTH_SHORT).show()
                })
                .show()
        }
        //これは予備コード
        //DB全削除用
        bt_delete.setOnClickListener {
            realm.beginTransaction()
            realm.where(user::class.java).findAll().deleteAllFromRealm()
            realm.commitTransaction()
        }
    }
}
open class user : RealmObject(){
    private var name : String = ""

    fun setName(name:String){
        this.name = name
    }

    fun getName():String{
        return name
    }

}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/et_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"
        android:hint="name"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/bt_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="add"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_name" />

    <ListView
        android:id="@+id/lv"
        android:layout_width="409dp"
        android:layout_height="636dp"
        android:layout_marginStart="1dp"
        android:layout_marginTop="1dp"
        android:layout_marginEnd="1dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/bt_add" />

    <Button
        android:id="@+id/bt_delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintEnd_toStartOf="@+id/bt_add"
        app:layout_constraintTop_toBottomOf="@+id/et_name" />

補足情報(FW/ツールのバージョンなど)

Android Studio Arctic Fox | 2020.3.1 Patch 1

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • hoshi-takanori

    2021/11/25 12:21 編集

    DB から削除できないのは、先に adapter.remove(adapter.getItem(id.toInt())) で adapter から削除してから、削除対象を val delete = adapter.getItem(id.toInt()) で adapter から取得しようとしてる (けど、adapter からは削除済みなので取得できない) からでは。

    キャンセル

  • okue

    2021/11/25 16:08

    hoshi-takanori様
    回答有難うございます。

    あと少しで出来そうなのですが、新たな問題が発生しました。
    名前を追加する時に、realmDBにも登録してるのですが、
    val delete = adapter.getItem(id.toInt())のdeleteをキーワードとして、
    realmDBから読込をしようと思っているのですが、
    val realm_delete = realm.where(user::class.java).equalTo("name",delete).findFirst()で検索かけると、user = proxy[{name:う}]と読込されて([う]は登録した時の名前です。)deleteとイコールになりません。
    realmで読込するとこのように読込されるのでしょうか?
    シンプルに[う]のみ読込されるものと思っておりました。
    分かりずらかったら申し訳ありません。

    キャンセル

  • okue

    2021/11/25 16:41

    hoshi-takanori様
    いつも回答有難うございます。

    なんとかDBも併せて削除することができました。

    キャンセル

回答 1

checkベストアンサー

0

Realm の環境が出来なかった(!)ので、データベース部分をインターフェースにして SQLite 実装クラスとしたモノを作って見ました。

・・・コード2本レイアウト2本(枚?)を張ろうとしたのですが(やはり)無理だったので、 https://github.com/Jimbe-github/teratail-q370729 に入れました。
(アクティビティのレイアウトも設定を少し弄りました。)

MainActivity だけ張っておきます。
DatabaseAccesser インターフェースを実装した Realm を使うクラスを作って dba = SQLiteDatabaseAccesser(this) の個所を書き換えれば動かせると思います。

MainActivity.kt

package com.teratail.q370729

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.appcompat.app.AlertDialog

class Memo {
  var _id: Long = 0 //データベース用
  var name:String = ""
  var age:Int = 0
  var text:String = ""
}

class MainActivity : AppCompatActivity() {
  lateinit var dba: DatabaseAccesser

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

    val et_name : EditText = findViewById(R.id.et_name)
    val bt_add : Button = findViewById(R.id.bt_add)
    val bt_delete : Button = findViewById(R.id.bt_delete)
    val lv : ListView = findViewById(R.id.lv)

    dba = SQLiteDatabaseAccesser(this)

    val adapter = MemoAdapter(dba)
    lv.adapter = adapter

    //bt_addを押すとet_nameに入力した内容をDBに保存とListViewに表示する処理を記載する
    bt_add.setOnClickListener {
      if(et_name.text.toString().isEmpty()){
        AlertDialog.Builder(this)
          .setTitle("未入力")
          .setMessage("名前を入力して下さい")
          .setPositiveButton("OK",null)
          .show()//et_nameが未入力の場合、アラートダイアログで表示
      }else{
        val memo = Memo()
        memo.name = et_name.text.toString()
        if(adapter.add(memo)) {
          et_name.text.clear()//DBに書き込みしたらEditTextの文字をクリアする
          Toast.makeText(applicationContext, "登録しました", Toast.LENGTH_SHORT).show()//トーストで表示
        }
      }
    }

    //ListViewをタップするとアラートダイアログを表示して、削除するかしないか判断する
    //合わせてDBに登録されているデータも一緒に削除する
    lv.setOnItemClickListener { _, _, position, _ ->
      AlertDialog.Builder(this)
        .setTitle("削除しますか??")
        .setPositiveButton("Yes", { _, _ ->
          //Yesを押下した時の処理
          //タップされたところのメモの削除
          if(adapter.remove(position)) {
            et_name.text.clear()
            //Toast.makeText(applicationContext,"削除しました",Toast.LENGTH_SHORT).show()
          }
        })
        .setNegativeButton("No", { _, _ ->
          Toast.makeText(applicationContext,"キャンセルしました",Toast.LENGTH_SHORT).show()
        })
        .show()
    }
    //これは予備コード
    //DB全削除用
    bt_delete.setOnClickListener {
      dba.deleteAll()
    }
  }

  override fun onDestroy() {
    dba.destroy()
    super.onDestroy()
  }
}

class MemoAdapter(val dba:DatabaseAccesser) : BaseAdapter() {
  private var memoList:MutableList<Memo>

  init {
    memoList = dba.readAll()
  }

  class ViewHolder(view:View) {
    var nameText:TextView
    var ageText:TextView
    var textText:TextView
    init {
      nameText = view.findViewById(R.id.nameText) as TextView
      ageText = view.findViewById(R.id.ageText) as TextView
      textText = view.findViewById(R.id.textText) as TextView
    }
  }
  override fun getCount(): Int {
    return memoList.size
  }
  override fun getItem(position: Int): Memo {
    return memoList[position]
  }
  override fun getItemId(position: Int): Long {
    return memoList[position]._id
  }
  override fun getView(position: Int, view: View?, parent: ViewGroup?): View {
    var v = view ?:
    LayoutInflater.from(parent!!.context).inflate(R.layout.row_layout,null).also {
      it.tag = ViewHolder(it)
    }

    val vh = v.tag as ViewHolder
    vh.nameText.text = memoList[position].name
    vh.ageText.text = memoList[position].age.toString()
    vh.textText.text = memoList[position].text

    return v
  }

  fun add(memo:Memo): Boolean {
    if(!dba.insert(memo)) return false
    memoList.add(memo)
    notifyDataSetChanged()
    return true
  }
  fun remove(position:Int): Boolean {
    val memo = memoList[position]
    if(!dba.delete(memo)) return false
    memoList.remove(memo)
    notifyDataSetChanged()
    return true
  }
}

interface DatabaseAccesser {
  fun readAll() : MutableList<Memo>
  fun insert(target:Memo):Boolean
  fun delete(target:Memo):Boolean
  fun deleteAll()
  fun destroy()
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/11/26 08:23

    jimbe様
    いつも回答有難うございます。

    わざわざコードまで作成して頂いて申し訳ありません。
    本当に有難うございます。
    是非参考にさせて頂きます。
    私自身、SQLiteが難しくて出来なかったので、勉強させて頂きます。

    キャンセル

  • 2021/11/26 11:46 編集

    SQLite は "SQL" という言語で操作する素の "リレーショナルデータベース(RDB)" でいわゆる "プログラム" とは全く違うものですから、難しく思われるかもしれませんね。
    ただ、全く違うだけに、 kotlin とは分けて考えることが出来るとも言えます。
    Realm や Room 等でも多少なりとも(考え方や用語等で) RDB や SQL の影響部分があると思いますので、 ("SQLite" というよりは) RDB(SQL) を知っておくことは役に立つと思います。

    キャンセル

  • 2021/11/26 11:58

    jimbe様
    いつも回答有難うございます。
    最初にSQLiteに挑戦してみたのですが、まったく理解出来なくて、Realmの方がSQLiteより実装が簡単で、且つ機能がいいと記載されているのを見て、Realmに至った次第です。
    SQLiteも今後使用することもあると思いますし、DBの基本だと思いますので、今一度勉強する必要があると思っております。
    本当にわざわざ貴重な時間を割いてコードを書いてくださり本当に感謝しております。私の個人的な話になるのですが、転職してプログラマーとして働きたいと考えております。プログラミングスクールで基礎を勉強して、現場で経験を積みたいと考えております。
    jimbe様のようなプログラマーになれるように努力していきたいと思っておりますので、今後ともよろしくお願い致します。

    キャンセル

  • 2021/11/26 16:03

    >Realmの方がSQLiteより実装が簡単で、且つ機能がいいと記載

    見解は人それぞれ状況それぞれに因るとは思いますが、後発の方が良くなるでしょう。
    でもそれは「SQLiteを使ってやろうとすると苦労する」部分が簡単になったり性能が良くなったりと言うことで、「使えるようになる」事が簡単という訳ではないかもしれません。
    プログラミングに限らず、前提となる知識・技能のハードルを何処まで下げられるかも各種ツールの目標・評価に入るとは思いますが、性能の面との兼ね合いが難しいでしょうね。

    キャンセル

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

  • ただいまの回答率 87.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る