Refactor: Convert WeatherForecastService to an interface-based implementation and improve coroutine handling

This commit is contained in:
Nebojsa Vuksic 2025-08-07 10:05:51 +02:00
parent 4673a445bf
commit 85f3a32137

View File

@ -1,36 +1,43 @@
package org.jetbrains.plugins.template.weatherApp.services
import com.intellij.openapi.components.Service
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jetbrains.plugins.template.weatherApp.model.*
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import kotlin.coroutines.CoroutineContext
import kotlin.random.Random
@Service
class WeatherForecastService(private val cs: CoroutineScope) {
private val _weatherForecast: MutableStateFlow<WeatherForecastData> = MutableStateFlow(WeatherForecastData.EMPTY)
val weatherForecast: StateFlow<WeatherForecastData> = _weatherForecast.asStateFlow()
interface WeatherForecastServiceApi {
/**
* Suspending function that returns Result<WeatherForecastData>.
* This allows callers to handle success/failure explicitly.
*
* @param location The location to get weather data for
* @return Result containing WeatherForecastData on success or exception on failure
*/
suspend fun loadWeatherForecastFor(location: Location): Result<WeatherForecastData>
}
fun loadWeatherForecastFor(location: Location) {
cs.launch(Dispatchers.IO) {
// TODO Cache data
emit(getWeatherData(location))
class WeatherForecastService(
private val networkCoroutineContext: CoroutineContext = Dispatchers.IO,
) : WeatherForecastServiceApi {
/**
* Function that returns a weather forecast for provided [location] param.
*
* @param location The location to get weather data for
* @return Result containing WeatherForecastData on success or exception on failure
*/
override suspend fun loadWeatherForecastFor(location: Location): Result<WeatherForecastData> {
return withContext(networkCoroutineContext) {
runCatching { getWeatherData(location) }
}
}
private fun emit(weatherData: WeatherForecastData) {
_weatherForecast.value = weatherData
}
/**
* Provides mock weather data for demonstration purposes.
* In a real application, this would fetch data from a weather API.
@ -41,6 +48,7 @@ class WeatherForecastService(private val cs: CoroutineScope) {
// Generate 7-day forecast data
val dailyForecasts = generateDailyForecasts(currentTime)
// Simulates a network request
delay(100)
return WeatherForecastData(