在我的应用程序中,我有一个后台任务(使用AsyncTask)从网站下载内容。
可以从两个单独的活动中调用此任务,并且可以将其调用两次。因此在“activity1”中调用后台任务“update”,并运行一段时间(通常需要5-10秒)。 然后当它运行时,用户切换到“activity2”并再次运行“更新”。 这会产生问题:当两者同时尝试清除数据库(命令:DELETE FROM表)时发生崩溃,导致“数据库锁定”错误。或者他们试图将相同的项目放在数据库中导致重复。
我尝试通过在任务处于活动状态时将静态布尔标志设置为true来解决此问题。 当调用该任务时,它将检查此标志,如果为true(即在另一个线程上运行相同的任务),则使用处理程序进入等待循环,直到该标志清除,然后返回。这样可以确保在后台任务返回时,更新已完成。我必须使用一个Looper:这有时会失败并出现错误“每个线程只能创建一个looper”。我真的有这样一种方式,只有一个looper可以启动,这是有问题的代码,它出现在后台任务的开头:
if (active) {
Looper.prepare();
handler = new Handler();
handler.postDelayed(new Runnable() {
int count = 0;
@Override
public void run() {
if (active) {
count++;
if (count < 1000)
handler.postDelayed(this, 100);
}
}
}, 100);
Looper.loop();
active = false;
return "done";
}
更糟糕的是,它似乎常常挂在这个循环中,而不会返回。
如何解决这种情况?
答案 0 :(得分:0)
为什么不使用同步?这听起来像是一个并发问题。为什么不确保如果第一个后台任务正在运行,那么第二个后台任务正在休眠,直到第一个任务完成为止。
或者以某种方式确保,如果用户切换到活动编号2,活动编号1的后台任务将被取消。
答案 1 :(得分:0)
您可以考虑使用IntentService代替AsyncTask。看看Android Service concept。 IntentService类确保一次只处理一个请求。
我发现this在使用Activity回调通信实现IntentService时非常有用。
答案 2 :(得分:0)
通过将数据库锁定问题包装到ContentProvider中解决了这个问题。除了在前一个实例完成之前再次调用方法的问题之外,我还遇到了在尝试写入数据库时在不同后台线程中运行的不同方法的问题。
官方设计允许在应用之间共享数据,它也非常适合在单个应用中的线程之间共享数据。 ContentProvider将确保不会发生锁定问题。