Java AsyncTask在Android中无法正确重新启动
我正在开发一个Android应用程序,我需要根据共享首选项中的变量不时显示提醒对话框。如果用户不想看到提醒消息,他也可以在“我的首选项”活动中禁用此选项。我使用AsyncTask类不时向用户显示提醒消息。用户可以随时按options按钮转到PreferenceActivity以启用/禁用提醒选项,并设置提醒和返回活动之间的暂停时间值。所以我检查onResume方法中的所有值。如果用户不想看到提醒消息,我需要完成当前的异步工作任务,或者如果用户在提醒之间更改了值,我需要使用新的暂停值重新启动当前的异步。但我看到我的AsyncTack有一个不可预测的行为:有时停止,有时停止,然后继续工作并显示消息),有时工作,有时-不()()))。下面是一段代码: 这是我的AsyncTack类Java AsyncTask在Android中无法正确重新启动,java,android,multithreading,android-asynctask,Java,Android,Multithreading,Android Asynctask,我正在开发一个Android应用程序,我需要根据共享首选项中的变量不时显示提醒对话框。如果用户不想看到提醒消息,他也可以在“我的首选项”活动中禁用此选项。我使用AsyncTask类不时向用户显示提醒消息。用户可以随时按options按钮转到PreferenceActivity以启用/禁用提醒选项,并设置提醒和返回活动之间的暂停时间值。所以我检查onResume方法中的所有值。如果用户不想看到提醒消息,我需要完成当前的异步工作任务,或者如果用户在提醒之间更改了值,我需要使用新的暂停值重新启动当前的
private class ReadReminderTask extends AsyncTask<Long, Void, Void> {
private long mRemindTime;
private volatile boolean running = true;
public ReadReminderTask(){
}
@Override
public Void doInBackground(Long... params){
mRemindTime = params[0];
while (running){
try{
Thread.sleep(mRemindTime);
publishProgress();
}
catch (Exception e){
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Void... progress) {
super.onProgressUpdate(progress);
// showReminder is a method where I show remind message
showReminder();
}
@Override
protected void onCancelled() {
running = false;
}
}
有人能帮我解决我的问题吗?这通常是个糟糕的解决方案<代码>异步任务在处理配置更改方面不是很好 根据延迟的时间长短,您可以使用
AlarmManager.setInexactRepeating
来显示这些对话框。您可以使用pendingent.getService
或pendingent.getBroadcast
创建新的pendingent
,具体取决于您希望实现显示对话框的方式—(从Service
您将只能显示类似系统的对话框)
并注册一个BroadcastReceiver,它将处理显示对话框的操作
如果延迟时间不长,您可以创建一个自定义的
ThreadPoolExecutor
,它将执行您想要的操作。我认为不应该使用AsyncTask来实现这一点<代码>线程。睡眠(mRemindTime)也很难看!如果你需要一个计时器,那就用它。这真的不是一个很好的方法。发生“不可预测行为”的原因是,即使在活动停止后,任务仍在运行。在您的onResume
中调用cancel
,不仅为时已晚,实际上根本没有做任何事情
查看处理程序.postDelayed
。你想要这样的东西:
在您的onCreate中
hdlr = new Handler();
reminder = new Runnable() { public void run() { showReminder(); } }
编辑以将必要的第二个参数添加到postDelayed
。。。在您的简历中
:
hdlr.postDelayed(reminder, mRemindTime);
。。。并且,在您的onPause
中:
hdlr.removeCallbacks(reminder);
请注意,AsyncTask.cancel()并不真正取消正在运行的任务。相反,它只设置一个标志来通知已请求取消。是否以及何时考虑此标志取决于AsyncTask实现
Thread.sleep返回后,当前代码不会检查取消。正确的实现方式如下:
public Void doInBackground(Long... params){
mRemindTime = params[0];
while (!isCancelled()){
try{
Thread.sleep(mRemindTime);
if(!isCancelled())
publishProgress();
}
catch (Exception e){
e.printStackTrace();
}
}
return null;
}
另外,asynctask中不需要属性“running”和onCancelled()方法。您可以使用方法“isCancelled()”。在您的else-if语句中,您正在创建一个新任务并执行它,我认为这不会停止旧任务。尝试取消任务,然后检查是否已取消,如果已取消,则使用不同参数启动同一任务,否则再次尝试取消并检查。不要每次都创建新任务。谢谢!我现在就试试这个。这里三分之三的解决方案告诉你不要“尝试这个”。真的,杜德:你做错了。好吧,但我在处理这个问题时太糊涂了,所以我尝试了所有的解决方案。)CountDownTime能在我的活动运行时以一定的时间间隔做一些工作吗?你是说这个onTick(long millisuntilly)
?谢谢!我会试试这个解决方案。报警管理器是一个很好的解决方案,如果它很重的话。AsyncTasks就是在ThreadPoolExecutor上运行的任务。使用自定义ThreadPoolExecutor重新实现AsyncTasks不是一个很好的解决方案。@G.Blake Meike是的,你是对的。但是你对发生的事情有了更多的控制权。我还可以假设使用Handler
和postDelayed
发布相同的Runnable
,尽管我不确定它将如何处理配置更改。在run()方法中,我需要在initrementer()之前创建类似Thread.SLeep(val)的东西?我说得对吗?谢谢!你的解决方案对我有效。我只添加了hdlr.postDelayed(提醒,时间);showReminder()之后的run()方法;打电话.@bukka.wh是的!感谢您指出我的代码遗漏了那个基本参数。编辑。
hdlr.removeCallbacks(reminder);
public Void doInBackground(Long... params){
mRemindTime = params[0];
while (!isCancelled()){
try{
Thread.sleep(mRemindTime);
if(!isCancelled())
publishProgress();
}
catch (Exception e){
e.printStackTrace();
}
}
return null;
}