带有 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 问题的主要内容,如果未能解决你的问题,请参考以下文章

SharedPreferences 不保存强制关闭应用程序

Xamarin Forms Sharedpreferences 交叉

Flutter:在 Stream 类中访问 SharedPreferences Provider / ChangeNotifier

Kotlin实现简单的学生信息管理系统

android: 内容提供器简介

在 Android 的密钥库中存储私钥