带有 SharedPreferences 的 Android 服务 setInexactRepeating asyncTask 问题
Posted
技术标签:
【中文标题】带有 SharedPreferences 的 Android 服务 setInexactRepeating asyncTask 问题【英文标题】:Android service setInexactRepeating asyncTask issue with SharedPreferences 【发布时间】:2016-10-12 10:28:00 【问题描述】:我的学生申请会在后台服务中下载分数,并检查分数是否比上次多。如果有任何新标记,它会推送通知并重写 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();
正如我所说,这主要是可行的,但有时 BroadcastReceiver 会立即连续触发两次 - 第一个会重写 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 ... I/Notification baked - id: 1077819997
06-11 18:14:28.004 ... 我/已保存和新:89、90
06-11 18:14:28.006 ... I/Notification baked - id: 1077820069
【问题讨论】:
有一个答案建议从不精确重复到重复。它没有帮助。 【参考方案1】:由于不准确的重复警报工作方式以及长时间运行的后台操作,很可能在问题发生时同时运行多个AsyncTask
实例。
来自AlarmManager
的文档:
您的闹钟的第一次触发不会在请求的时间之前,但 在那之后的几乎一个完整的时间间隔内,它可能不会发生。在 此外,而重复警报的总周期将是 请求,任何两次连续触发警报之间的时间 可能会有所不同。
对于如此短的间隔,我建议使用setRepeating()
而不是setInexactRepeating()
和
在Service
中保留AsyncTask
的实例。
然后,你可以这样做:
if(task.getStatus == AsyncTask.Status.FINISHED)
task = new DownloadDataTask();
task.execute(context.getString(R.string.LOGIN_PAGE_URL), username, password);
为了防止您的AsyncTask
的多个实例同时运行。
【讨论】:
我在一个带有 postDelayed 的处理程序中使用了它,它就像一个魅力。非常感谢。以上是关于带有 SharedPreferences 的 Android 服务 setInexactRepeating asyncTask 问题的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin Forms Sharedpreferences 交叉
Flutter:在 Stream 类中访问 SharedPreferences Provider / ChangeNotifier