每周在特定日期重置数据库值的最佳方法(Android - 房间)

Best way to reset a database value every week on specific day (Android - Room)

我正在开发一个 Android 应用程序,该应用程序具有每周一次的功能,也就是说,用户必须在一周中的每一天将这一天标记为完成。这个值在我的数据库中是一个布尔值,用 false 初始化,当用户单击复选框时设置为 true。一切正常。

但我的问题是,每次新的一周开始时,我都需要在一周的所有 7 天中将此布尔值“重置”为 false。我不需要过去几周的记录。重要的是实际的一周(周日到周六)。

这个任务很简单,我只需要这样做:

for(WeekDay day: dao.getWeekDays()){
            day.setDone(false);
            dao.updateWeekDay(day); //update the value in database
        }

所以,我做了一些研究(我是 android 的新手)并发现 Android 有不同的计划服务,如 JobScheduler 或 AlarmManager。我的应用程序设计为 Android 10+ (API 29+)。 您认为解决我的问题的最佳方法是什么? 这是一项非常简单的任务(它不会占用太多电池、互联网...),我需要每周在特定的一天(星期日)执行此操作。另外,这个任务需要尽快完成,即使 phone 在周日关闭。它不需要是后台服务,但我需要保证当用户打开应用程序并且这是新的一周时,之前需要调用该方法,但前提是在前一周没有调用它.

有人有想法吗?

好的,我想我找到了一个简单的解决方案,基于我阅读的其他类似答案。每次应用程序启动时,我只需要 运行 这些功能。我不需要使用任何后台服务,例如 WorkManager。 我只需要在 SharedPreferences 中存储系统重置值的最后日期。然后,每次我打开该应用程序时,它都会检查今天是否与上次重置日期不同。如果它是真的,那么我 运行 问题中的“for cycle”并在 SharedPreferences 中将最后重置日期更新为今天。如果它是假的,我什么都不做。

方法 inSameCalendarWeek 检查今天是否在同一年的同一周(Locale.US 保证一周从星期日开始。但我可以将其更改为 Locale.getDefault()更灵活)。另外,例如,如果 12 月 31 日与 1 月 1 日在同一周,即使它们在不同的年份,该方法也会 return true.

private void checkAndResetDoneDays() {
        long lastResetDay = settings.getLong(LAST_DAY_RESET, 0);
        LocalDate date = Instant.ofEpochMilli(lastResetDay).atZone(ZoneId.systemDefault()).toLocalDate();
        if (!inSameCalendarWeek(date)) {
            resetDoneDays();
            settings.edit()
                    .putLong(LAST_DAY_RESET, LocalDate.now(ZoneId.systemDefault()).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli())
                    .commit();
        }
    }

public boolean inSameCalendarWeek(LocalDate firstDate) {
        LocalDate secondDate = LocalDate.now(ZoneId.systemDefault());
        // get a reference to the system of calendar weeks in US Locale (to guarantee that week starts on Sunday)
        WeekFields weekFields = WeekFields.of(Locale.US);
        // find out the calendar week for each of the dates
        int firstDatesCalendarWeek = firstDate.get(weekFields.weekOfWeekBasedYear());
        int secondDatesCalendarWeek = secondDate.get(weekFields.weekOfWeekBasedYear());
        /*
         * find out the week based year, too,
         * two dates might be both in a calendar week number 1 for example,
         * but in different years
         */
        int firstWeekBasedYear = firstDate.get(weekFields.weekBasedYear());
        int secondWeekBasedYear = secondDate.get(weekFields.weekBasedYear());
        // return if they are equal or not
        return firstDatesCalendarWeek == secondDatesCalendarWeek
                && firstWeekBasedYear == secondWeekBasedYear;
    }