java 在小吃店操作中,我如何确保从数据库中永久删除软删除记录是安全的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31056939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In a snackbar action, how can I be sure it's safe to permanently delete a soft-deleted record from the database?
提问by chathura
I am using Snackbar in android and I have implemented an action so that user can undo the action (the action is clearing all the items in the listview).Removing and adding the items back to the listview has already been done and working fine.
我在 android 中使用 Snackbar 并且我已经实现了一个操作,以便用户可以撤消该操作(该操作正在清除列表视图中的所有项目)。删除项目并将其添加回列表视图已经完成并且工作正常。
My issue is that, items are stored in sqlite database and how can I delete the items from tables? (How can I know that the user has not clicked the undo button, so that I can completely remove the data from database).
我的问题是,项目存储在 sqlite 数据库中,如何从表中删除项目?(我怎么知道用户没有点击撤销按钮,以便我可以从数据库中完全删除数据)。
This is the code inside OnOptionsItemSelcted()
这是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;
So if the user has not clicked the undo button during the visible period of the snackbar, then I need to permanently delete the data from database.
所以如果用户在snackbar可见期间没有点击撤销按钮,那么我需要从数据库中永久删除数据。
Any solutions for this?
对此有任何解决方案吗?
回答by natario
As far as I know, it is by design. You should:
据我所知,这是设计使然。你应该:
- Delete the item as soon as the user taps the delete button;
- Store it temporarily in a class variable;
- If the user taps Undo, add the item again to the database.
- 用户点击删除按钮后立即删除项目;
- 将其临时存储在类变量中;
- 如果用户点击撤消,则再次将项目添加到数据库中。
This approach is safer and more robust; you shouldn't wait for the snackbar to be dismissed, because that action could not even happen. Just think of user force-quitting the app while the snackbar is still on: should the item be deleted or not? It should.
这种方法更安全、更稳健;您不应该等待小吃店被关闭,因为该操作甚至不会发生。想想用户在小吃店仍然打开的情况下强制退出应用程序:是否应该删除该项目?这应该。
A more trustworthy source is g+ post by Ian Lake (deleted because of G+ deprecation). In the comments you can read:
更值得信赖的来源是 Ian Lake 的 g+ 帖子(由于 G+ 弃用而删除)。在评论中,您可以阅读:
you want your UI to react immediately (not wait for the snackbar to disappear) - most systems (particularly those that sync to an external server) have the concept of a 'soft delete' where things are marked as deleted. In those cases, an undo action would just be unmarking the record as deleted. This system works even if the user were to leave the app before the snackbar finishes (you can't assume the snackbar will always complete its animation!).
The easiest way to do that is to temporarily save the record elsewhere (even a local variable), then re-insert it if they happen to hit the undo button.
您希望您的 UI 立即做出反应(而不是等待小吃栏消失)——大多数系统(尤其是那些同步到外部服务器的系统)都有“软删除”的概念,其中的内容被标记为已删除。在这些情况下,撤消操作只是将记录取消标记为已删除。即使用户在小吃店完成之前离开应用程序,该系统也能正常工作(您不能假设小吃店将始终完成其动画!)。
最简单的方法是将记录临时保存在别处(甚至是局部变量),然后在碰巧点击撤消按钮时重新插入它。
回答by Irritator
Android Support library v23 added Snackbar.Callbackwhich you can use to listen if the snackbar was dismissed by user or timeout.
Android 支持库 v23 添加了Snackbar.Callback,您可以使用它来侦听Snackbar是否被用户关闭或超时。
Example borrowed from astinxs post:
从astinx的帖子中借用的示例:
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();
回答by WFranczyk
Example:
例子:
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());
It may be a good idea to add a little to the snackbar.getDuration() time (100-200ms?) as timers are not very exact in terms of timing and this way they may get called just before the snackbar is about to close, althought the possibility is rather small in this case.
添加一点到snackbar.getDuration() 时间(100-200ms?)可能是个好主意,因为计时器在时间方面不是很精确,这样它们可能会在snackbar 即将关闭之前被调用,虽然在这种情况下可能性很小。
回答by Mahozad
If you don't want to delete the record from database immediately, try this:
如果您不想立即从数据库中删除记录,请尝试以下操作:
// 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();
回答by Vampire
My way is to hv "deleted" column that is boolean, just change the stat to be true if deleted then undo to change back stat to be false, also u maybe want trash controller or scheduler to delete all the false values on every week.
我的方法是将“已删除”列设为布尔值,只需将 stat 更改为 true 如果删除然后撤消将 stat 更改为 false,您也可能希望垃圾控制器或调度程序每周删除所有错误值。