[Android]ListViewでonItemLongClickからのDBデータ削除の手順について
解決済
回答 1
投稿
- 評価
- クリップ 1
- VIEW 2,599
お世話になっております。
Androidアプリで、
1 ローカルDBからデータ取得
2 ListViewに一覧表示
3 list長押しでActionBarの部分に削除ボタン表示
4 OkでDBから削除、画面再描画で対象データが非表示に、
というアプリを作ろうとしています(Gmailアプリみたいな動作です)。
ここで今、4番の削除後の画面再描画のところで詰まっています。
「ListView 更新」などで調べるとnotifyDataSetChanged
がよくヒットするので試してみても、変わりません。
削除後、別画面に遷移して戻ってもう一度Listを構築すれば、削除したデータは一覧に出ませんが、
Gmailアプリみたいに削除したらすぐに一覧から消えるようにするには、どうしたらいいのでしょうか。
稚拙ですが、主だった部分のコードを載せます(メソッドの中身はところどころ省略)。
SQliteはActiveAndroidで操作しています。
Adapterを操作せずに直接DeleteしているからnotifyDataSetChanged
が効かないと思うのですが、
ActiveAndroidを使うと下記のような書き方しか思いつかず。。
# モデル定義
@Table(name="Members")
public class Members extends Model{
@Column(name="Name")
public String Name;
}
public class MyListItem{
...
public Long getId() { return id; }
public String getName() { return name; }
...
}
public class MySampleList extends AppCompatActivity {
protected MyListItem myListItem;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
final List<MyListItem> lists = new ArrayList<>();
List<Members> members = new Select().from(Members.class).orderBy("id DESC").execute();
for(Members member : members){
myListItem = new MyListItem(
member.getId(),
member.Name
);
lists.add(myListItem);
}
MyBaseAdaptor mba = new MyBaseAdaptor(this, lists);
ListView mlist = (ListView) this.findViewById(R.id.mListView);
mlist.setAdaptor(mba);
mlist.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
final ActionBar actionBar = getSupportActionBar();
startActionMode(new ActionMode.Callback() { //List長押しでActionMode
...
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()){
case R.id.icon_discard: // 削除アイコンを押した場合
Long member_id = lists.get(position).getId();
new Delete().from(Members.class).where("id = ?", member_id).execute();
//このあたりで notifyDataSetChanged ?
return true;
}
return false;
}
}
}
});
}
public class MyBaseAdaptor extends BaseAdapter{
private Context context;
private List<MyListItem> members;
public MyBaseAdaptor(Context context, List<MyListItem> members) {
this.context = context;
this.members = members;
}
@Override
public int getCount() { }
@Override
public Object getItem(int position) {}
@Override
public long getItemId(int position) {}
@Override
public View getView(int position, View convertView, ViewGroup parent) {}
}
}
アドバイスいただけると幸いです。「ここ見ろ」などサイトの紹介でも結構です。
よろしくお願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
ListViewにセットされているAdapterからデータを削除してからListView#notifyDataSetChangedを呼ぶ必要があります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/04/03 19:52
よく分かってなく恐縮ですが、Adapterからデータを削除すると、同時にDBからも消えるのか、DBから消す処理が別途必要なのかが、分かりません。。
mlist.setAdaptor(mba);
でsetしたmbaからremoveすると思っているのですが、removeメソッドが使えずAndroidStudioに怒られます。。
2016/04/03 20:19
DBとは切り離されているため、Adapterからデータを削除してもDBには影響がありません。
ArrayListAdapterを継承した方が楽そうですね。
2016/04/03 23:05
色々試行錯誤しましたが、最終的に下記のようにしたら動きました()。
1) BaseAdapterを継承したMyBaseAdaptorにremoveItem(position)というメソッド追加。
2) removeItem内でnew Delete.from ~ でActiveAndroid経由でDBレコード削除。かつmembers.remove(potision)でMyBaseAdaptorが保持するデータからも対象を削除。
3) startActoinMode#onActionItemClicked にて、myBaseAdaptor#removeItemを呼び出す。
myBaseAdapter#removeItemを呼び出す際、myBaseAdapter(のインスタンス)を定義した箇所が悪いのか、finalをつけないとエラーになるのが気持ち悪いですが。
>ArrayListAdapterを継承した方が楽そうですね。
こちらはちなみに、ArrayAdapterでしょうか?
http://developer.android.com/intl/ja/reference/android/widget/ArrayAdapter.html
こういうDBのデータを使う場合はArrayAdapterかBaseAdapterで独自に作る方がいいのか、分からないのですが。。
2016/04/03 23:32
DBの更新処理をAdapterの中に入れてしまうのはあまりお勧めできません。
せっかく分離した、データと見た目を再結合してしまうからです。
誤記でした、ArrayAdapterですね。
今回のように配列からAdapterを作るときは追加、挿入、削除ができるからです。
2016/04/06 12:03
> finalをつけないといけないのはmyBaseAdapterがローカル変数なため、押したタイミングでは到達できないインスタンスになるからですよ。
なるほどです。
finalだらけになりそうで気持ち悪かったのですが、この場合は仕方ないですかね。。
> DBの更新処理をAdapterの中に入れてしまうのはあまりお勧めできません。
> せっかく分離した、データと見た目を再結合してしまうからです。
なるほど、おっしゃる通りですね。。
Adapter内でDBの処理はしないで、分離してみます!