Wie kann ich auf Datums- oder Zeitzone -Änderungen beobachten, um die Benutzeroberfläche mit MVVM, Uscase und Hilt zu akAndroid

Forum für diejenigen, die für Android programmieren
Anonymous
 Wie kann ich auf Datums- oder Zeitzone -Änderungen beobachten, um die Benutzeroberfläche mit MVVM, Uscase und Hilt zu ak

Post by Anonymous »

Ich habe eine Schnittstelle namens TimeZonemonitor zur Überwachung der Zeitzone oder des Datumsänderungen. Änderungen .
Code:

Code: Select all

TimeZoneMonitor

Code: Select all

interface TimeZoneMonitor {
val currentTimeZone: Flow
val currentDate:Flow
}
< /code>
TimeZoneBroadcastMonitor

Code: Select all

@Singleton
class TimeZoneBroadcastMonitor @Inject constructor(
@ApplicationContext private val context: Context,
@ApplicationScope appScope: CoroutineScope,
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
) : TimeZoneMonitor {

override val currentTimeZone: SharedFlow =
callbackFlow {
// Send the default time zone first.
trySend(TimeZone.currentSystemDefault())

// Registers BroadcastReceiver for the TimeZone changes
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action != Intent.ACTION_TIMEZONE_CHANGED) return

val zoneIdFromIntent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
null
} else {
// Starting Android R we also get the new TimeZone.
intent.getStringExtra(Intent.EXTRA_TIMEZONE)?.let { timeZoneId ->
// We need to convert it from java.util.Timezone to java.time.ZoneId
val zoneId = ZoneId.of(timeZoneId, ZoneId.SHORT_IDS)
// Convert to kotlinx.datetime.TimeZone
zoneId.toKotlinTimeZone()
}
}

// If there isn't a zoneId in the intent, fallback to the systemDefault, which should also reflect the change
trySend(zoneIdFromIntent ?: TimeZone.currentSystemDefault())
}
}

trace("TimeZoneBroadcastReceiver.register") {
context.registerReceiver(receiver, IntentFilter(Intent.ACTION_TIMEZONE_CHANGED))
}

// Send here again, because registering the Broadcast Receiver can take up to several milliseconds.
// This way, we can reduce the likelihood that a TZ change wouldn't be caught with the Broadcast Receiver.
trySend(TimeZone.currentSystemDefault())

awaitClose {
context.unregisterReceiver(receiver)
}
}
// We use to prevent multiple emissions of the same type, because we use trySend multiple times.
.distinctUntilChanged()
.conflate()
.flowOn(ioDispatcher)
// Sharing the callback to prevent multiple BroadcastReceivers being registered
.shareIn(appScope, SharingStarted.WhileSubscribed(5_000), 1)

}
< /code>
GetHomeUseCase

Code: Select all

class GetHomeUseCase @Inject constructor(
private val universalisRepository: UniversalisRepository,
private val userDataRepository: UserDataRepository,
) {

operator fun invoke(
date: Int,
): Flow {
return combine(
userDataRepository.userData,
universalisRepository.countUniversalis(UniversalisResourceQuery(date)),
) { userData, count ->
if (count == 0 &&  date.isDateValid()) {
universalisRepository.insertFromRemote(UniversalisResourceQuery(date))
}
val newData = universalisRepository.getUniversalisForTest(date).first()
HomeResource(
date = date,
data = newData,
count = count,
dynamic = userData
)
}
}
}
< /code>
HomeViewModel

Code: Select all

@HiltViewModel
class HomeViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val analyticsHelper: AnalyticsHelper,
timeZoneMonitor:TimeZoneMonitor,
val userDataRepository: UserDataRepository,
getHomeUseCase: GetHomeUseCase,
) : ViewModel() {

private val selectedTopicIdKey = "selectedTopicIdKey"
private val route: UniversalisRoute = savedStateHandle.toRoute()

private val selectedTopicId = savedStateHandle.getStateFlow(
key = selectedTopicIdKey,
initialValue = route.initialTopicId.toString(),
)

val currentTimeZone = timeZoneMonitor.currentTimeZone
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(5_000),
TimeZone.currentSystemDefault(),
)
val zi = ZoneId.of(currentTimeZone.value.id)
val time = ZonedDateTime.now(zi)
private val newDate=time.format(DateTimeFormatter.ofPattern("yyyyMMdd")).toInt()
private var selectedDate = savedStateHandle.getStateFlow(
key = "date",
initialValue = newDate,
)

val uiState: StateFlow = combine(
selectedTopicId,
selectedDate,
getHomeUseCase.invoke(
date = selectedDate.value,
),
HomeUiState::HomeData,
).catch {
val error = HomeUiState.HomeError(
date = selectedDate.value,
message = it.message!!
)
analyticsHelper.logHomeErrorEvent(error)
emit(error)
}//.distinctUntilChanged()
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = HomeUiState.Loading,
)
}

sealed interface HomeUiState {
data object Loading : HomeUiState

data class HomeData(
val selectedTopicId: String?,
val selectedDate:Int,
val topics: HomeResource,
) : HomeUiState

data class HomeError(
val date: Int,
val message: String
) : HomeUiState {

override fun toString(): String {
return "Date: $date Msg: $message"
}
}

data object Empty : HomeUiState

}
< /code>
HomeScreen
(Jetpack Compose)

Code: Select all

@ExperimentalLayoutApi
@Composable
fun HomeScreen(
uiState: HomeUiState,
modifier: Modifier,
onTopicClick: (String) -> Unit,
currentTimeZone: State,
currentDate: State,
) {

when (uiState) {
HomeUiState.Empty -> EmptyState(modifier = modifier)
is HomeUiState.HomeData -> {
HomeItems(uiState = uiState, onTopicClick = onTopicClick, currentTimeZone=currentTimeZone,currentDate=currentDate,modifier = modifier, haveDate=true)
}

HomeUiState.Loading -> LoadingState(modifier = modifier)
is HomeUiState.HomeError -> {
HomeItems(uiState = uiState, onTopicClick = onTopicClick, currentTimeZone=currentTimeZone,currentDate=currentDate,modifier = modifier, haveDate=false)
}
}
}
< /code>

@ExperimentalLayoutApi
@Composable
fun HomeItems(
uiState: HomeUiState,
onTopicClick: (String) -> Unit,
modifier: Modifier,
haveDate: Boolean = false,
currentTimeZone: State,
currentDate: State

) {

// ...
val data = uiState as HomeUiState.HomeData

Text(
text = data.topics.data.fecha,
modifier = Modifier.padding(2.dp),
textAlign = TextAlign.Center,
)
}
Mein Problem mit diesem Code ist, dass, wenn ich das Datum im System ändere, die Homedata Informationen nicht mit dem neuen Datum aktualisiert werden.>

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post