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

如何通过Hilt注入可灵活修改格式的SimpleDateFormat?

优化ViewModel中日期格式化的灵活性问题

你的现有实现存在两个核心问题:一是格式模板硬编码在类继承的构造方法中,无法灵活切换;二是SimpleDateFormat本身非线程安全,在ViewModel这种可能被多线程调用的场景下容易引发隐蔽的bug。下面是具体的优化方案:

1. 替换线程不安全的SimpleDateFormat,改用组合模式重构

放弃继承SimpleDateFormat,改用Java 8+的DateTimeFormatter(Android需开启Desugar支持,或使用ThreeTenABP兼容旧版本)——它是不可变类,天然线程安全,且API设计更合理。同时通过组合而非继承的方式封装格式化逻辑,让格式模板和Locale可配置。

重构后的日期格式化类

import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Locale

class DateFormatter @Inject constructor(
    // 默认保留原格式和Locale,可通过构造参数覆盖
    private var formatPattern: String = "EEE, MMM dd",
    private var locale: Locale = Locale.US
) {
    // DateTimeFormatter是不可变的,修改格式时直接替换实例即可
    private var dateTimeFormatter = DateTimeFormatter.ofPattern(formatPattern, locale)

    fun convertUnixTimeToDate(unixTime: Long): String {
        return try {
            Instant.ofEpochSecond(unixTime)
                .atZone(ZoneId.systemDefault()) // 转换为当前时区的时间
                .format(dateTimeFormatter)
        } catch (e: Exception) {
            // 更友好的错误提示,而非直接返回异常toString
            e.localizedMessage ?: "Invalid timestamp"
        }
    }

    // 支持运行时动态修改格式和Locale
    fun updateFormat(newPattern: String, newLocale: Locale = this.locale) {
        this.formatPattern = newPattern
        this.locale = newLocale
        this.dateTimeFormatter = DateTimeFormatter.ofPattern(newPattern, newLocale)
    }
}

2. 通过依赖注入实现多格式实例的灵活复用

如果你的App需要多种日期格式(比如短格式、长格式),可以用Hilt的@Qualifier注解区分不同的格式化实例,在ViewModel中按需注入。

定义Qualifier区分不同格式

import javax.inject.Qualifier
import kotlin.annotation.AnnotationRetention.BINARY

@Qualifier
@Retention(BINARY)
annotation class ShortDateFormat

@Qualifier
@Retention(BINARY)
annotation class LongDateFormat

在Hilt Module中提供不同配置的实例

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import java.util.Locale

@Module
@InstallIn(SingletonComponent::class)
object DateFormatterModule {

    @Provides
    @ShortDateFormat
    fun provideShortDateFormatter(): DateFormatter {
        return DateFormatter("EEE, MMM dd", Locale.US)
    }

    @Provides
    @LongDateFormat
    fun provideLongDateFormatter(): DateFormatter {
        return DateFormatter("yyyy-MM-dd HH:mm:ss", Locale.US)
    }
}

在ViewModel中按需注入

import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class WeatherViewModel @Inject constructor(
    private val repository: WeatherRepository,
    @ShortDateFormat private val shortDateFormatter: DateFormatter,
    @LongDateFormat private val longDateFormatter: DateFormatter
) : ViewModel() {

    // 根据业务场景使用不同的格式化器
    fun getShortDisplayDate(unixTime: Long) = shortDateFormatter.convertUnixTimeToDate(unixTime)
    
    fun getFullDisplayDate(unixTime: Long) = longDateFormatter.convertUnixTimeToDate(unixTime)
}

3. 运行时动态切换格式(可选)

如果需要在App运行时根据用户设置切换日期格式,直接调用dateFormatter.updateFormat()方法即可:

// 示例:切换为中文长格式
dateFormatter.updateFormat("yyyy年MM月dd日 HH:mm:ss", Locale.CHINA)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:35:18