如何通过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
相关产品推荐
相关产品推荐

