我正在开发一个Android应用程序,我需要根据共享首选项的变量不时显示提醒对话框。如果用户不想看到提醒消息,他也可以在我的PreferenceActivity中禁用此选项。我正在使用AsyncTask类不时向用户显示提醒消息。用户可以随时按选项按钮转到PreferenceActivity以启用/禁用提醒选项并在提醒之间设置暂停时间值,然后返回活动。所以我正在检查onResume方法中的所有值。如果用户不想看到提醒消息,我需要完成当前工作的AsyncTask,或者如果用户在提醒之间更改了值,我需要使用新的暂停值重新启动当前的AsyncTack。但我看到我的AsyncTack有一种不可预测的行为:有时会停止,有时不会继续工作并显示消息)))),有时它有效,有时 - 不是)))))。这是一段代码:
这是我的AsyncTack类
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;
}
}
这是我的Activity的onResume方法,我需要在其中显示提醒消息:
if(!settings.getBoolean("needToRemind", false)) {
mReadReminderTask.cancel(true);
} else if(settings.getBoolean("needToRemind", false)) {
mReadReminderTask = new ReadReminderTask();
mReadReminderTask.execute(settings.getLong("timeRemind", 1));
}
任何人都可以帮我解决问题吗?
答案 0 :(得分:1)
这真的不是一个很好的方法。发生“不可预测的行为”是因为即使在Activity
停止后您仍然运行任务。 cancel
中对onResume
的调用不仅太晚了,实际上根本没有做任何事情。
看看Handler.postDelayed
。你想要这样的东西:
在onCreate
hdlr = new Handler();
reminder = new Runnable() { public void run() { showReminder(); } }
已编辑为必须延期的第二个参数添加
...在onResume
:
hdlr.postDelayed(reminder, mRemindTime);
......以及onPause
:
hdlr.removeCallbacks(reminder);
答案 1 :(得分:1)
请注意,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;
}
同时属性&#39;运行&#39;并且不需要asynctask中的onCancelled()方法。您可以使用方法&#39; isCancelled()&#39;代替。
答案 2 :(得分:0)
这通常是一个糟糕的解决方案。 AsyncTasks
在处理配置更改时效果不佳。
根据延迟的时间长短,您可以使用AlarmManager.setInexactRepeating
来显示这些对话框。您可以使用PendingIntent
或PendingIntent.getService
创建新的PendingIntent.getBroadcast
,具体取决于您希望如何实现显示对话框 - (来自Service
您将只能显示系统状态对话框)。
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intentStart = new Intent();
intentStart.setAction(SHOW_DIALOG_ACTION);
PendingIntent pendingIntentStart = PendingIntent.getBroadcast(context, 0, intentStart, 0);
注册一个BroadcastReceiver,它将处理显示对话框。
如果延迟时间不长,您可以创建一个自定义ThreadPoolExecutor
,它可以满足您的需求。
答案 3 :(得分:0)
我不认为应该使用AsyncTask。 Thread.sleep(mRemindTime)
也非常难看!如果您需要使用计时器CountDownTimer。