web-dev-qa-db-ja.com

スナックバーアクションで、ソフト削除されたレコードをデータベースから完全に削除しても安全であることをどのように確認できますか?

Androidでスナックバーを使用しており、ユーザーがアクションを取り消すことができるようにアクションを実装しました(アクションはリストビューのすべてのアイテムをクリアしています)。リストビューへのアイテムの削除と追加すでに行われ、正常に動作しています。

私の問題は、アイテムがsqliteデータベースに格納されていることと、テーブルからアイテムを削除するにはどうすればよいですか? (データベースからデータを完全に削除できるように、ユーザーが[元に戻す]ボタンをクリックしていないことをどのようにして知ることができますか)。

これは内部のコードですOnOptionsItemSelcted()

case R.id.action_clear:
        final List<Word> temp = new ArrayList<Word>(data);
        data.clear();
        adapter.notifyDataSetChanged();
        View view = findViewById(R.id.layoutFavWords);
        Snackbar.make(view,"Deleted Saved Selection.", Snackbar.LENGTH_LONG).
        setAction("Undo", new OnClickListener() {

            @Override
            public void onClick(View v) {
                for(Word word:temp)
                    data.add(Word);
                adapter.notifyDataSetChanged(); 
            }

        }).show();
        break;

スナックバーが表示されている間にユーザーが[元に戻す]ボタンをクリックしなかった場合、データベースからデータを完全に削除する必要があります。

これに対する解決策はありますか?

20
chathura

私の知る限り、これは仕様によるものです。あなたがすべき:

  • ユーザーが削除ボタンをタップしたらすぐにアイテムを削除します。
  • 一時的にクラス変数に格納します。
  • ユーザーが[元に戻す]をタップした場合は、アイテムをデータベースに再度追加します。

このアプローチはより安全で堅牢です。そのスナックバーが消えるのを待つべきではありません。スナックバーがオンのときにユーザーがアプリを強制終了することを考えてみてください。アイテムを削除する必要があるかどうか。そうすべき。

より信頼できるソースは、Ian Lakeによるg +投稿です(G +の廃止により削除されました)。コメントであなたは読むことができます:

uIをすぐに反応させたい(スナックバーが消えるのを待たない)-ほとんどのシステム(特に外部サーバーと同期するシステム)には、削除済みとしてマークされる「ソフト削除」の概念があります。これらの場合、元に戻すアクションは、レコードを削除済みとしてマーク解除するだけです。このシステムは、ユーザーがスナックバーが終了する前にアプリを離れた場合でも機能します(スナックバーが常にアニメーションを完了するとは限りません!)。

これを行う最も簡単な方法は、レコードを他の場所(ローカル変数も含む)に一時的に保存し、[元に戻す]ボタンを押した場合はそれを再挿入することです。

28
natario

Androidサポートライブラリv23が追加されました Snackbar.Callback これは、ユーザーまたはタイムアウトによってスナックバーが閉じられた場合に聞くために使用できます。

astinx sポストから借りた例:

Snackbar.make(getView(), "Hi there!", Snackbar.LENGTH_LONG).setCallback( new Snackbar.Callback() {
            @Override
            public void onDismissed(Snackbar snackbar, int event) {
                switch(event) {
                    case Snackbar.Callback.DISMISS_EVENT_ACTION:
                        Toast.makeText(getActivity(), "Clicked the action", Toast.LENGTH_LONG).show();
                        break;
                    case Snackbar.Callback.DISMISS_EVENT_TIMEOUT:
                        Toast.makeText(getActivity(), "Time out", Toast.LENGTH_LONG).show();
                        break;
                }
            }

            @Override
            public void onShown(Snackbar snackbar) {
                Toast.makeText(getActivity(), "This is my annoying step-brother", Toast.LENGTH_LONG).show();
            }
        }).setAction("Go away!", new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        }).show();
10
Irritator

例:

final Java.util.Timer timer = new Timer();
Snackbar snackbar = Snackbar.make(...).setAction("Undo", new OnClickListener() {
        @Override
        public void onClick(View v) {
            timer.cancel();
            for(Word word:temp)
                data.add(Word);
            adapter.notifyDataSetChanged(); 
        }
    }).show();
timer.schedule(new TimerTask() {
    public void run() {
        // delete from db
    }
}, snackbar.getDuration());

タイマーはタイミングに関して非常に正確ではないため、スナックバーが閉じる直前に呼び出される可能性があるため、sackbar.getDuration()時間に少し追加することをお勧めします(100〜200ミリ秒?)。この場合、可能性はかなり小さいですが。

4
WFranczyk

データベースからレコードをすぐに削除したくない場合は、これを試してください:

// Backup the item for undo
int itemIndex = viewHolder.getAdapterPosition();
Item item = adapter.getItem(itemIndex);

// Delete only from the adapter
adapter.removeItem(itemIndex);

Snackbar.make(getView(), "Item deleted", LENGTH_LONG)
        .addCallback(new BaseCallback<Snackbar>() {
            public void onDismissed(Snackbar transientBottomBar, int event) {
                if (event != DISMISS_EVENT_ACTION) {
                    // Dismiss wasn't because of tapping "UNDO"
                    // so here delete the item from databse
                }
            }
        })
        .setAction("UNDO", v -> adapter.addItem(item, itemIndex))
        .show();
2
Mahozad

私の方法は、ブール値の「削除された」列をhvすることです。削除された場合は統計をtrueに変更し、元に戻して統計をfalseに変更します。また、ゴミ箱コントローラまたはスケジューラで毎週すべてのfalse値を削除することもできます。

0
Vampire