Android服务setInexactRepeating SharedPreferences的asyncTask问题

时间:2016-06-11 15:27:40

标签: android android-asynctask broadcastreceiver sharedpreferences android-service

我的学生申请在后台服务中下载标记,并检查是否有比上次更多的分数。如果有任何新标记,则会推送通知并重写 sharedPreferences 中的标记数。它有效,但有时它会同时为同一个标记创建多个通知。

IntentService 会触发广播接收器

public int onStartCommand(Intent intent, int flags, int startId) {
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent i = new Intent(getApplicationContext(), CheckNewMarksReceiver.class);
    PendingIntent alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);

    alarmManager.setInexactRepeating(
            AlarmManager.ELAPSED_REALTIME_WAKEUP,
            0,
            2500, alarmIntent);

    return START_STICKY;
}

广播接收器 onReceive 方法初始化sharedPreferences属性和numberOfMarksSaved并启动下载数据的AsyncTask:

DownloadDataTask task = new DownloadDataTask();
task.execute(context.getString(R.string.LOGIN_PAGE_URL), username, password);

dataPreferences = context.getApplicationContext().getSharedPreferences(context.getString(R.string.SHARED_PREFERENCES), Context.MODE_PRIVATE);
numberOfMarksSaved = dataPreferences.getInt(context.getString(R.string.PREFERENCE_NUMBER_OF_MARKS_KEY), -1);

AsyncTasks onPostExecute 方法检查下载的标记数是否大于上次:

if (numberOfDownloadedMarks > numberOfMarksSaved) {
    ...
    notifyUserAbout(newMarks, response); // method to fire a notification
}

dataPreferences
    .edit()
    .putInt(context.getString(R.string.PREFERENCE_NUMBER_OF_MARKS_KEY),
            numberOfDownloadedMarks)
    .apply();

正如我所说,这主要是有效的,但有时会立即触发连续两次触发 - 第一个重写sharedPreferences中的值,但第二个没有“注意到”共享首选项中的值已更改。我该如何防止这种情况?

修改 我试过甚至setRepeating而不是setInexactRepeating - 没有改变(我怀疑android alarmManager时移)。这是我的日志:

06-11 18:14:27.732 ...我/即将:下载新数据

06-11 18:14:27.761 ...我/即将:下载新数据

06-11 18:14:27.907 ...我/保存&新:89,90

06-11 18:14:27.933 ...我/通知已烘焙 - 身份证号码:1077819997

06-11 18:14:28.004 ...我/保存&新:89,90

06-11 18:14:28.006 ...我/通知烘焙 - 身份证号码:1077820069

1 个答案:

答案 0 :(得分:1)

由于重复警报的不精确运行以及长时间运行的后台操作,很可能在问题发生时同时运行多个x个实例。

来自AsyncTask的文档:

  

您的闹钟首次触发不会在请求的时间之前,但是   在此之后几乎整整一段时间内可能不会发生。在   另外,重复报警的整个周期将为   要求,任何两次连续发出警报之间的时间   可能会有所不同。

对于如此短的间隔,我建议使用AlarmManager代替setRepeating()

setInexactRepeating()中保留AsyncTask的实例。

然后,你可以这样做:

Service

防止if(task.getStatus == AsyncTask.Status.FINISHED) { task = new DownloadDataTask(); task.execute(context.getString(R.string.LOGIN_PAGE_URL), username, password); } 的多个实例同时运行。