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

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

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

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Q&A

解決済

1回答

4175閲覧

AndroidのRecyclerviewにおいてリストのスワイプ削除を行っても、リストに表示されるデータが更新されません。

circulay

総合スコア8

Java

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

0グッド

0クリップ

投稿2019/08/25 16:13

<実現したいこと>
Recyclerview(入力保存のあるSQLiteデータベース)を使ったリストのデータをスワイプ削除する。

<問題点>
ItemTouchHelper(onSwiped)によって、Recyclerviewで作ったリストのデータをスワイプし、画面上から削除する動き自体はできています。
しかし、その状態で新しいデータを追加保存したり、他の画面から遷移したりすると、削除したはずのデータがそのままリストに表示されてしまいます。
notifyDataSetChanged();を入れても、リストに表示されるデータを更新することができない状態です。

どのようにすれば解決できるのでしょうか。
アドバイスなど頂けたら幸いです。よろしくお願いします。

1(MaintenanceDataShow.java)・・・データを読み込み、Recyclerviewのリストに表示する

Java

1package torach.java_conf.gr.jp.carmaintenance; 2 3import android.content.Intent; 4import android.database.Cursor; 5import android.database.sqlite.SQLiteDatabase; 6import android.support.design.widget.FloatingActionButton; 7import android.support.v7.app.AppCompatActivity; 8import android.os.Bundle; 9import android.support.v7.widget.DividerItemDecoration; 10import android.support.v7.widget.LinearLayoutManager; 11import android.support.v7.widget.RecyclerView; 12import android.support.v7.widget.helper.ItemTouchHelper; 13import android.view.KeyEvent; 14import android.view.Menu; 15import android.view.MenuItem; 16import android.view.View; 17 18import java.util.ArrayList; 19 20public class MaintenanceDataShow extends AppCompatActivity { 21 22 private MaintenanceDataHelper helper; 23 private Cursor cursor; 24 private RecyclerView recyclerView; 25 private LinearLayoutManager manager; 26 private RecyclerView.Adapter adapter; 27 private ArrayList<ListItem> data; 28 private SQLiteDatabase db; 29 30 @Override 31 protected void onCreate(Bundle savedInstanceState) { 32 super.onCreate(savedInstanceState); 33 setContentView(R.layout.activity_maintenance_data_show); 34 35 //FloatingActionButtonの設置 36 FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 37 fab.setOnClickListener(new View.OnClickListener() { 38 @Override 39 public void onClick(View v) { 40 Intent intent = new Intent(getApplication(), InputMaintenanceData.class); 41 startActivity(intent); 42 } 43 }); 44 45 46 //SQLiteデータベース読み込み 47 readData(); 48 49 //区切り線 50 RecyclerView.ItemDecoration itemDecoration = 51 new DividerItemDecoration(this, DividerItemDecoration.VERTICAL); 52 recyclerView.addItemDecoration(itemDecoration); 53 54 55 //スワイプ削除読み出し 56 listsSwipe(); 57 58 } 59 60 //SQLite保存データ呼び込み 61 public void readData() { 62 63 try { 64 65 helper = new MaintenanceDataHelper(MaintenanceDataShow.this); 66 db = helper.getReadableDatabase(); 67 68 //テーブル内のデータを配列に渡す 69 String[] columns = {"date", "category", "price", "notes"}; 70 71 cursor = db.query("maintenanceDB", columns, null, null, null, null, null); 72 73 if(cursor != null && cursor.getCount() > 0) { 74 75 data = new ArrayList<>(); 76 77 while (cursor.moveToNext()) { 78 79 ListItem dataItem = new ListItem(); 80 81 //dataItem.setId(cursor.getInt(cursor.getColumnIndex(MaintenanceDataHelper.ROW_ID))); 82 //dataItem.setId((new Random()).nextLong()); 83 84 dataItem.setCategory(cursor.getString(cursor.getColumnIndex(MaintenanceDataHelper.ROW_CATEGORY))); 85 dataItem.setDate(cursor.getString(cursor.getColumnIndex(MaintenanceDataHelper.ROW_NAME))); 86 dataItem.setPrice(cursor.getString(cursor.getColumnIndex(MaintenanceDataHelper.ROW_PRICE))); 87 dataItem.setNotes(cursor.getString(cursor.getColumnIndex(MaintenanceDataHelper.ROW_NOTES))); 88 data.add(dataItem); 89 } 90 } 91 92 } finally { 93 if (cursor != null) { 94 cursor.close(); 95 } 96 db.close(); 97 } 98 99 //リサイクルビューのレイアウト 100 recyclerView = (RecyclerView) findViewById(R.id.Recycle_View_Layout); 101 recyclerView.setHasFixedSize(true); 102 103 //レイアウトマネージャー作成 104 manager = new LinearLayoutManager(this); 105 manager.setOrientation(LinearLayoutManager.VERTICAL); 106 recyclerView.setLayoutManager(manager); 107 108 //アダプターをRecyclerManagerに設定 109 adapter = new ViewAdapter(data); 110 recyclerView.setAdapter(adapter); 111 112 } 113 114 //ItemTouchHelper.Simpleを使ったリストのスワイプ削除 115 public void listsSwipe() { 116 ItemTouchHelper.SimpleCallback mIth = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) { 117 118 @Override 119 public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { 120 return false; 121 } 122 123 @Override 124 public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 125 int position = viewHolder.getAdapterPosition(); 126 //((ViewAdapter)recyclerView.getAdapter()).removeItem(position); 127 data.remove(position); 128 adapter.notifyDataSetChanged(); 129 130 } 131 132 }; 133 new ItemTouchHelper(mIth).attachToRecyclerView(recyclerView); 134 135 } 136 137 138 //オプションメニューの制御 139 //表示 140 @Override 141 public boolean onCreateOptionsMenu(Menu menu) { 142 // オプションメニューを作成する 143 getMenuInflater().inflate(R.menu.option_menu_maintenancedatashow,menu); 144 return super.onCreateOptionsMenu(menu); 145 } 146 147 //動作処理 148 @Override 149 public boolean onOptionsItemSelected(MenuItem item) { 150 151 // オプションメニュー 152 switch (item.getItemId()){ 153 case R.id.menu_Item5: 154 moveToCarDataShow(); 155 break; 156 } 157 158 return super.onOptionsItemSelected(item); 159 } 160 161 //画面遷移 162 //車種データ画面に遷移 163 public void moveToCarDataShow() { 164 Intent intent = new Intent(getApplication(), CarDataShow.class); 165 startActivity(intent); 166 } 167 168 169 //バックボタン無効化(スプラッシュ画面に戻らない) 170 @Override 171 public boolean onKeyDown(int keyCode, KeyEvent event) { 172 if(keyCode == KeyEvent.KEYCODE_BACK) { 173 return false; 174 } 175 return super.onKeyDown(keyCode, event); 176 } 177 178 179} 180

2(MaintenanceDataHelper.java)・・・データベースヘルパー

java

1package torach.java_conf.gr.jp.carmaintenance; 2 3import android.content.Context; 4import android.database.sqlite.SQLiteDatabase; 5import android.database.sqlite.SQLiteOpenHelper; 6 7 8public class MaintenanceDataHelper extends SQLiteOpenHelper { 9 10 //テーブル情報定義 11 public static final String TABLE_NAME = "maintenanceDB"; 12 public static final String ROW_ID = "_id"; 13 public static final String ROW_NAME = "date"; 14 public static final String ROW_CATEGORY = "category"; 15 public static final String ROW_PRICE = "price"; 16 public static final String ROW_NOTES = "notes"; 17 18 //データベースファイル名とバージョン情報 19 public static final String DB_NAME = "maintenance.db"; 20 private static final int DB_VERSION = 1; 21 22 //コンストラクタ 23 public MaintenanceDataHelper(Context context) { 24 25 super(context, DB_NAME, null, DB_VERSION); 26 } 27 28 //テーブル作成 29 private static final String SQL_CREATE = 30 31 "CREATE TABLE IF NOT EXISTS " 32 + TABLE_NAME 33 + " (" 34 + ROW_ID 35 + " INTEGER PRIMARY KEY AUTOINCREMENT," 36 + ROW_NAME 37 + " TEXT," 38 + ROW_CATEGORY 39 + " TEXT," 40 + ROW_PRICE 41 + " TEXT," 42 + ROW_NOTES 43 + " TEXT" 44 + ");"; 45 46 47 //データベースのバージョンアップ 48 @Override 49 public void onCreate(SQLiteDatabase db) { 50 db.execSQL(SQL_CREATE); 51 } 52 53 //データベースのバージョンアップ後のテーブル再作成 54 @Override 55 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 56 db.execSQL("DROP TABLE IF EXISTS maintenanceDB"); 57 onCreate(db); 58 } 59 60}

3(ViewAdapter.java)・・・アダプター

java

1package torach.java_conf.gr.jp.carmaintenance; 2 3import android.support.v7.widget.RecyclerView; 4import android.view.LayoutInflater; 5import android.view.View; 6import android.view.ViewGroup; 7 8import java.util.ArrayList; 9 10public class ViewAdapter extends RecyclerView.Adapter<ViewHolder> { 11 12 13 private ArrayList<ListItem> data; 14 15 //コンストラクター 16 public ViewAdapter(ArrayList<ListItem> data) { 17 this.data = data; 18 19 } 20 21 22 //ビューホルだ生成 23 @Override 24 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 25 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.data_field, parent,false); 26 return new ViewHolder(view); 27 } 28 29 //ビューにデータを割り当てる・リストの項目の生成 30 @Override 31 public void onBindViewHolder(final ViewHolder holder, int position) { 32 33 ListItem dataSet = data.get(position); 34 35 holder.category.setText(dataSet.getCategory()); 36 holder.date.setText(dataSet.getDate()); 37 holder.price.setText(dataSet.getPrice()); 38 holder.notes.setText(dataSet.getNotes()); 39 } 40 41 //データ項目数を取得 42 @Override 43 public int getItemCount() 44 { 45 return data == null ? 0 : data.size(); 46 } 47} 48

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

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

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

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

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

guest

回答1

0

ベストアンサー

データベースからの削除がありません.

投稿2019/08/25 17:49

jimbe

総合スコア12648

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

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

circulay

2019/08/26 01:08

ありがとうございます。 該当するリストデータの主キーを取得した上で、その主キーを含む行をテーブルから削除することを試みました。しかし、スワイプするデータの主キーを取得できずにいます。 主キーを取得するにはどのように記述するとよいでしょうか。 @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { int position = viewHolder.getAdapterPosition(); data.remove(position); adapter.notifyDataSetChanged(); try { db = helper.getWritableDatabase(); db.delete(MaintenanceDataHelper.TABLE_NAME, MaintenanceDataHelper.ROW_ID + " = ?", new String[]{String.valueOf(position)}); } finally {db.close(); }
jimbe

2019/08/26 02:07

このような場合に使用することを想定して, [getItemId]( https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#getitemid ) というメソッドがあります. 先ず, ListItem に _ID 列も保持するようにします. アダプタの [hasStableIds]( https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#hasstableids ) を true を返すようにします. getItemId を実装し, position から _ID 列の値を返すようにします. onSwiped で Adapter.getItemId(position) として _ID を得ます. 蛇足ですが, data の操作やデータベースへのアクセスなど様々な処理の詳細を直接メソッド内に並べるのは, オブジェクト指向的に好ましくないと思います. 例えば data の操作はアダプタが担当し, データベースへのアクセスは別の専用クラスが担当するようにし, リスナではそれらを呼び出すだけとするように, 担当クラスを決めて詳細はそれらに封じ込める形にすることで, 役割や責任を明確にして全体を整理することがオブジェクトを使う理由でもあります.
jimbe

2019/08/26 02:18

「封じ込める」という意味では, MaintenanceDataShow にフィールドとして MaintenanceDataHelper や Cursor を持っていることも, 止めたほうが良いかと思います. これらは使用時に生成され, 同じメソッド内で役割を終えています. そのようなモノは各メソッド内で宣言するべきで, そうでなければ不要なオブジェクトが残り続けることになります. また, 読む側(後日の作者本人も含みます)においても, フィールドは「メソッド内で完結しないモノ」という認識で読みますので, 不必要な注意を払うことになります.
circulay

2019/08/26 13:08

とても貴重なアドバイスを頂き、本当にありがとうございます。 ご助言を参考にして修正したところ、少しデータベースから削除されるようになってきました。 しかし、リストからスワイプしたデータとは別のデータ(1つ下の行)が削除されてしまいます。 またリストの最終行のデータを削除しようとすると、IndexOutOfBoundsExceptionエラーが発生します。 onSwipedの中のpositionの扱い方に問題があるのでしょうか。 <修正した部分> ○ListItemに追記  private long id;  long getId() {return id;}  void setId(long id) {this.id = id;} ○アダプター  @Override public long getItemId(int position) {return data.get(position).getId(); } *以下hasStableIdsはエラーになります(cannot verride) @Override public boolean hasStableIds () { return true; } ○onSwiped内 final int position = viewHolder.getAdapterPosition(); data.remove(position); adapter.notifyDataSetChanged(); long id = adapter.getItemId(position); ---省略--- db.delete("maintenanceDB", "_id=?", new String[]{String.valueOf(id)});
jun74

2019/08/26 13:22 編集

「data.remove(position);」を「long id = adapter.getItemId(position);」の先にやっているからでは? db.deleteが1で1件削除を確認してから、 data.remove(position); adapter.notifyDataSetChanged(); を実施すべきと考えます。 データが消えてないのに行消すのは変なので。
circulay

2019/08/26 13:26

ご指摘いただいたところを直したら解決しました。 ありがとうございました。 とても助かりました。
jimbe

2019/08/26 13:40

jun74 さん, 説明不足の所ご指摘ありがとうございます.
jun74

2019/08/26 14:17

>circulayさん 直って良かったです。 >jimbeさん いえいえ。これからもよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問