添加了顶部时间更新
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
package com.sw.inbound.utils
|
||||
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* 时间格式化工具类
|
||||
*/
|
||||
object DateTimeUtils {
|
||||
|
||||
/**
|
||||
* 获取完整中文日期格式(示例:2025年6月11日 星期三)
|
||||
*/
|
||||
fun getChineseDateString(date: Date = Date()): String {
|
||||
return SimpleDateFormat("yyyy年M月d日 EEEE", Locale.CHINA).format(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取带时间的完整中文格式(示例:2025年6月11日 星期三 14:30)
|
||||
*/
|
||||
fun getChineseDateTimeString(date: Date = Date()): String {
|
||||
return SimpleDateFormat("yyyy年M月d日 EEEE HH:mm:ss", Locale.CHINA).format(date)
|
||||
}
|
||||
|
||||
// 使用线程安全的日期格式化(避免 SimpleDateFormat 的线程安全问题)
|
||||
private val dateFormat by lazy {
|
||||
SimpleDateFormat("yyyy年M月d日 EEEE", Locale.CHINA)
|
||||
}
|
||||
private val timeFormat by lazy {
|
||||
SimpleDateFormat("HH:mm:ss", Locale.CHINA)
|
||||
}
|
||||
|
||||
fun getChineseDateTimePair(date: Date = Date()): Pair<String, String> {
|
||||
return dateFormat.format(date) to timeFormat.format(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* 实时时间流(每秒更新)
|
||||
* @param intervalMillis 更新间隔(默认1秒)
|
||||
*/
|
||||
fun realTimeChineseDateFlow(intervalMillis: Long = 1000) = flow {
|
||||
while (true) {
|
||||
emit(getChineseDateTimePair())
|
||||
delay(intervalMillis)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.sw.inbound.utils
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object GsonUtils {
|
||||
|
||||
// 默认的 Gson 实例
|
||||
private val defaultGson: Gson by lazy {
|
||||
GsonBuilder()
|
||||
.setDateFormat("yyyy-MM-dd HH:mm:ss") // 设置日期格式
|
||||
.disableHtmlEscaping() // 禁止转义HTML标签
|
||||
.create()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认配置的 Gson 实例
|
||||
*/
|
||||
fun getGson(): Gson = defaultGson
|
||||
|
||||
/**
|
||||
* 将对象转换为 JSON 字符串
|
||||
* @param obj 要转换的对象
|
||||
* @return JSON 字符串
|
||||
*/
|
||||
fun toJson(obj: Any?): String {
|
||||
return if (obj == null) "" else defaultGson.toJson(obj)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 JSON 字符串转换为对象
|
||||
* @param json JSON 字符串
|
||||
* @param clazz 目标类
|
||||
* @return 转换后的对象
|
||||
*/
|
||||
fun <T> fromJson(json: String?, clazz: Class<T>): T? {
|
||||
if (json.isNullOrEmpty()) {
|
||||
return null
|
||||
}
|
||||
return try {
|
||||
defaultGson.fromJson(json, clazz)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 JSON 字符串转换为对象 (支持泛型)
|
||||
* @param json JSON 字符串
|
||||
* @param type 类型令牌,用于获取泛型类型
|
||||
* @return 转换后的对象
|
||||
*/
|
||||
fun <T> fromJson(json: String?, type: Type): T? {
|
||||
if (json.isNullOrEmpty()) {
|
||||
return null
|
||||
}
|
||||
return try {
|
||||
defaultGson.fromJson(json, type)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 JSON 字符串转换为 List 对象
|
||||
* @param json JSON 字符串
|
||||
* @param clazz List 中的元素类型
|
||||
* @return 转换后的 List 对象
|
||||
*/
|
||||
fun <T> fromJsonList(json: String?, clazz: Class<T>): List<T>? {
|
||||
if (json.isNullOrEmpty()) {
|
||||
return null
|
||||
}
|
||||
return try {
|
||||
val type = TypeToken.getParameterized(List::class.java, clazz).type
|
||||
defaultGson.fromJson<List<T>>(json, type)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 JSON 字符串转换为 Map 对象
|
||||
* @param json JSON 字符串
|
||||
* @param keyClazz Map 的 key 类型
|
||||
* @param valueClazz Map 的 value 类型
|
||||
* @return 转换后的 Map 对象
|
||||
*/
|
||||
fun <K, V> fromJsonMap(
|
||||
json: String?,
|
||||
keyClazz: Class<K>,
|
||||
valueClazz: Class<V>
|
||||
): Map<K, V>? {
|
||||
if (json.isNullOrEmpty()) {
|
||||
return null
|
||||
}
|
||||
return try {
|
||||
val type = TypeToken.getParameterized(Map::class.java, keyClazz, valueClazz).type
|
||||
defaultGson.fromJson<Map<K, V>>(json, type)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为另一种类型的对象
|
||||
* @param obj 源对象
|
||||
* @param clazz 目标类型
|
||||
* @return 转换后的对象
|
||||
*/
|
||||
fun <T> convert(obj: Any?, clazz: Class<T>): T? {
|
||||
if (obj == null) {
|
||||
return null
|
||||
}
|
||||
return fromJson(toJson(obj), clazz)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.sw.inbound.utils
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import com.sw.plate.App
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class SPUtil private constructor(context: Context, private val spName: String) {
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var instance: SPUtil? = null
|
||||
|
||||
fun getInstance(
|
||||
context: Context = App.getContext(),
|
||||
spName: String = "default_sp"
|
||||
): SPUtil {
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: SPUtil(context.applicationContext, spName).also { instance = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val sharedPreferences by lazy {
|
||||
context.getSharedPreferences(spName, Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
// 基础存储方法
|
||||
fun put(key: String, value: Any?) {
|
||||
when (value) {
|
||||
null -> remove(key) // 存入null视为删除
|
||||
is String -> sharedPreferences.edit { putString(key, value) }
|
||||
is Int -> sharedPreferences.edit { putInt(key, value) }
|
||||
is Long -> sharedPreferences.edit { putLong(key, value) }
|
||||
is Float -> sharedPreferences.edit { putFloat(key, value) }
|
||||
is Boolean -> sharedPreferences.edit { putBoolean(key, value) }
|
||||
is Set<*> -> sharedPreferences.edit { putStringSet(key, value as Set<String>) }
|
||||
else -> throw IllegalArgumentException("Unsupported type: ${value.javaClass.name}")
|
||||
}
|
||||
notifyDataChanged(key)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T> get(key: String, defaultValue: T? = null): T? {
|
||||
return when (defaultValue) {
|
||||
is String -> sharedPreferences.getString(key, defaultValue) as T
|
||||
is Int -> sharedPreferences.getInt(key, defaultValue) as T
|
||||
is Long -> sharedPreferences.getLong(key, defaultValue) as T
|
||||
is Float -> sharedPreferences.getFloat(key, defaultValue) as T
|
||||
is Boolean -> sharedPreferences.getBoolean(key, defaultValue) as T
|
||||
is Set<*> -> sharedPreferences.getStringSet(key, defaultValue as Set<String>) as T
|
||||
null -> when {
|
||||
sharedPreferences.contains(key) -> get(key, "") as? T // 尝试作为String获取
|
||||
else -> null
|
||||
}
|
||||
|
||||
else -> throw IllegalArgumentException("Unsupported type: ${defaultValue.javaClass.name}")
|
||||
}
|
||||
}
|
||||
|
||||
fun remove(key: String) {
|
||||
if (sharedPreferences.contains(key)) {
|
||||
sharedPreferences.edit { remove(key) }
|
||||
notifyDataChanged(key)
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
sharedPreferences.edit { clear() }
|
||||
notifyDataChanged(null)
|
||||
}
|
||||
|
||||
fun contains(key: String): Boolean {
|
||||
return sharedPreferences.contains(key)
|
||||
}
|
||||
|
||||
// 监听变化
|
||||
private val dataChangeFlow = MutableStateFlow(0)
|
||||
|
||||
private fun notifyDataChanged(key: String?) {
|
||||
dataChangeFlow.value++
|
||||
}
|
||||
|
||||
fun observeKey(key: String): Flow<Any?> {
|
||||
return dataChangeFlow.map { get(key) }
|
||||
}
|
||||
|
||||
// 属性委托支持
|
||||
fun int(key: String, default: Int = 0) = SpProperty(key, default)
|
||||
fun long(key: String, default: Long = 0L) = SpProperty(key, default)
|
||||
fun float(key: String, default: Float = 0f) = SpProperty(key, default)
|
||||
fun boolean(key: String, default: Boolean = false) = SpProperty(key, default)
|
||||
fun string(key: String, default: String = "") = SpProperty(key, default)
|
||||
fun stringSet(key: String, default: Set<String> = emptySet()) = SpProperty(key, default)
|
||||
|
||||
inner class SpProperty<T>(private val key: String, private val defaultValue: T) :
|
||||
ReadWriteProperty<Any?, T> {
|
||||
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
return get(key, defaultValue) ?: defaultValue
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||
put(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user