You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android端使用Kotlin实现numerator与denominator周自动切换的方法

实现方案

1. 周类型核心计算工具类

优先使用java.time系列API实现逻辑,避免旧Calendar类的周起始日、时区等坑,Android 8.0以下可以通过开启核心库脱糖兼容:

import java.time.DayOfWeek
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.temporal.ChronoUnit
import java.time.temporal.TemporalAdjusters

enum class WeekType {
    NUMERATOR, DENOMINATOR
}

object WeekCalculator {
    // 替换为你校历中已知为NUMERATOR的任意周一日期作为基准
    private val BASE_NUMERATOR_MONDAY: LocalDate = LocalDate.of(2024, 9, 2)

    fun getCurrentWeekType(): WeekType {
        val currentMonday = LocalDate.now()
            .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
        val weeksDiff = ChronoUnit.WEEKS.between(BASE_NUMERATOR_MONDAY, currentMonday)
        // 偶数间隔为NUMERATOR,奇数为DENOMINATOR,可根据需求调换规则
        return if (weeksDiff % 2 == 0L) WeekType.NUMERATOR else WeekType.DENOMINATOR
    }

    // 获取下一次切换的日期(本周日0点)
    fun getNextSwitchTime(): LocalDate = LocalDate.now()
        .with(TemporalAdjusters.next(DayOfWeek.SUNDAY))
}

如果需要兼容Android 8.0以下版本,在模块级build.gradle中添加脱糖配置即可:

android {
    defaultConfig {
        coreLibraryDesugaringEnabled true
    }
}
dependencies {
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
}

2. Fragment实时展示逻辑

在生命周期onResume中触发UI更新,保证用户每次切回页面都能拿到最新的周类型:

class WeekTypeFragment : Fragment() {
    private var _binding: FragmentWeekTypeBinding? = null
    private val binding get() = _binding!!
    private var switchWatcherJob: Job? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentWeekTypeBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onResume() {
        super.onResume()
        updateWeekTypeDisplay()
        // 启动周日0点自动切换监听
        startAutoSwitchWatcher()
    }

    override fun onPause() {
        super.onPause()
        // 页面不可见时取消监听,避免资源浪费
        switchWatcherJob?.cancel()
    }

    private fun updateWeekTypeDisplay() {
        when(WeekCalculator.getCurrentWeekType()) {
            WeekType.NUMERATOR -> binding.weekTypeTv.text = "当前为分子周"
            WeekType.DENOMINATOR -> binding.weekTypeTv.text = "当前为分母周"
        }
    }

    // 前台场景下自动监听切换时间,到点自动刷新UI
    private fun startAutoSwitchWatcher() {
        switchWatcherJob?.cancel()
        switchWatcherJob = viewLifecycleOwner.lifecycleScope.launch {
            val delayMillis = ChronoUnit.MILLIS.between(
                LocalDateTime.now(),
                WeekCalculator.getNextSwitchTime().atStartOfDay()
            )
            delay(delayMillis)
            updateWeekTypeDisplay()
            // 重新启动下一轮切换监听
            startAutoSwitchWatcher()
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

额外说明

  • 如果需要后台场景下也能触发切换通知,可以用WorkManager设置一次性定时任务,每次切换后重新调度下一次任务即可,功耗远低于常驻服务
  • 如果有调休、假期跳过周次的需求,可以在WeekCalculator中添加排除特定周的逻辑
  • 基准周的日期务必根据校历调整,保证周类型计算和学校安排一致

内容的提问来源于stack exchange,提问作者onesector

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 20:36:04