@@ -15,23 +15,21 @@ import com.zj.model.room.entity.CityInfo
1515import com.zj.model.weather.WeatherDailyBean
1616import com.zj.model.weather.WeatherNowBean
1717import com.zj.utils.XLog
18- import com.zj.utils.checkCoroutines
1918import com.zj.utils.checkNetConnect
2019import com.zj.utils.view.showToast
2120import com.zj.utils.weather.getLocationForCityInfo
2221import com.zj.weather.R
2322import com.zj.weather.widget.today.LOCATION_REFRESH
2423import dagger.hilt.android.lifecycle.HiltViewModel
2524import kotlinx.coroutines.Dispatchers
26- import kotlinx.coroutines.Job
2725import kotlinx.coroutines.async
2826import kotlinx.coroutines.delay
2927import kotlinx.coroutines.flow.Flow
3028import kotlinx.coroutines.flow.MutableStateFlow
3129import kotlinx.coroutines.flow.StateFlow
3230import kotlinx.coroutines.flow.asStateFlow
31+ import kotlinx.coroutines.flow.channelFlow
3332import kotlinx.coroutines.launch
34- import kotlinx.coroutines.withContext
3533import javax.inject.Inject
3634import kotlin.collections.set
3735import kotlin.system.measureTimeMillis
@@ -51,29 +49,15 @@ class WeatherViewModel @Inject constructor(
5149) : AndroidViewModel(application) {
5250
5351 companion object {
52+ // 缓存过期时间,暂定为15分钟
5453 private const val FIFTEEN_MINUTES = 60 * 1000 * 15
5554 }
5655
57- private var weatherJob: Job ? = null
58- private var updateCityJob: Job ? = null
59-
6056 private val weatherMap = hashMapOf<String , Pair <Long , WeatherModel >>()
6157
6258 val cityInfoList: Flow <List <CityInfo >> = weatherRepository.refreshCityList()
6359
64- private val _weatherModel = MutableStateFlow <PlayState <WeatherModel >>(PlayLoading )
65- val weatherModel: StateFlow <PlayState <WeatherModel >> = _weatherModel .asStateFlow()
66-
67- private fun onWeatherModelChanged (playState : PlayState <WeatherModel >) {
68- if (playState == _weatherModel .value) {
69- XLog .d(" onWeatherModelChanged no change" )
70- return
71- }
72- viewModelScope.launch {
73- _weatherModel .emit(playState)
74- }
75- }
76-
60+ // 刷新的flow,用于记录下拉刷新状态
7761 private val _isRefreshing = MutableStateFlow (false )
7862
7963 val isRefreshing: StateFlow <Boolean >
@@ -85,36 +69,45 @@ class WeatherViewModel @Inject constructor(
8569 // A fake 2 second 'refresh'
8670 _isRefreshing .emit(true )
8771 val time = measureTimeMillis {
88- getWeather (cityInfo)
72+ weatherModel (cityInfo, true )
8973 }
9074 delay(if (time > 1000L ) time else 1000L )
9175 _isRefreshing .emit(false )
9276 }
9377 }
9478
95- fun getWeather (cityInfo : CityInfo ) {
96- val location = getLocationForCityInfo(cityInfo)
97- if (weatherMap.containsKey(location)) {
98- val weather = weatherMap[location]
99- if (weather != null && weather.first + FIFTEEN_MINUTES > System .currentTimeMillis()) {
100- XLog .d(" Direct return" )
101- onWeatherModelChanged(PlaySuccess (weather.second))
102- return
79+
80+ /* *
81+ * 综合起来直接调用,即数据观察、数据请求、重试等都使用这个函数来进行
82+ *
83+ * @param cityInfo 城市信息
84+ * @param refresh 是否要刷新,默认为否,否的话就是使用缓存数据
85+ *
86+ * @return flow,可观测数据流
87+ */
88+ fun weatherModel (cityInfo : CityInfo , refresh : Boolean = false): Flow <PlayState <WeatherModel >> =
89+ channelFlow {
90+ val location = getLocationForCityInfo(cityInfo)
91+ if (weatherMap.containsKey(location) && ! refresh) {
92+ val weather = weatherMap[location]
93+ if (weather != null && weather.first + FIFTEEN_MINUTES > System .currentTimeMillis()) {
94+ XLog .d(" Direct return" )
95+ send(PlaySuccess (weather.second))
96+ }
10397 }
104- }
105- if (! getApplication<Application >().checkNetConnect()) {
106- showToast(getApplication(), R .string.bad_network_view_tip)
107- onWeatherModelChanged(PlayError (IllegalStateException (" 当前没有网络" )))
108- return
109- }
110- weatherJob.checkCoroutines()
111- weatherJob = viewModelScope.launch(Dispatchers .IO ) {
112- val weatherNow = async { weatherRepository.getWeatherNow(location) }.await()
98+ if (! getApplication<Application >().checkNetConnect()) {
99+ showToast(getApplication(), R .string.bad_network_view_tip)
100+ send(PlayError (IllegalStateException (" 当前没有网络" )))
101+ }
102+ val weatherNow =
103+ async(Dispatchers .IO ) { weatherRepository.getWeatherNow(location) }.await()
113104 // 这块由于这两个接口有问题,和风天气的jar包问题,提交反馈人家说没问题。。qtmd。
114105 // 目前发现在S版本上有问题,R中没有发现
115- val weather24Hour = async { weatherRepository.getWeather24Hour(location) }.await()
116- val weather7Day = async { weatherRepository.getWeather7Day(location) }.await()
117- val airNow = async { weatherRepository.getAirNow(location) }.await()
106+ val weather24Hour =
107+ async(Dispatchers .IO ) { weatherRepository.getWeather24Hour(location) }.await()
108+ val weather7Day =
109+ async(Dispatchers .IO ) { weatherRepository.getWeather7Day(location) }.await()
110+ val airNow = async(Dispatchers .IO ) { weatherRepository.getAirNow(location) }.await()
118111 val weatherLifeIndicesList =
119112 async { weatherRepository.getWeatherLifeIndicesList(location) }.await()
120113 buildWeekWeather(weather7Day?.second, weatherNow)
@@ -127,12 +120,8 @@ class WeatherViewModel @Inject constructor(
127120 weatherLifeList = weatherLifeIndicesList
128121 )
129122 weatherMap[location] = Pair (System .currentTimeMillis(), weatherModel)
130- withContext(Dispatchers .Main ) {
131- onWeatherModelChanged(PlaySuccess (weatherModel))
132- }
133- XLog .w(" For the weather:$location " )
123+ send(PlaySuccess (weatherModel))
134124 }
135- }
136125
137126 /* *
138127 * 为了构建7天天气的柱状图
@@ -178,8 +167,7 @@ class WeatherViewModel @Inject constructor(
178167 * @param result Address
179168 */
180169 fun updateCityInfo (location : Location , result : MutableList <Address >) {
181- updateCityJob.checkCoroutines()
182- updateCityJob = viewModelScope.launch(Dispatchers .IO ) {
170+ viewModelScope.launch(Dispatchers .IO ) {
183171 weatherRepository.updateCityInfo(location, result)
184172 getApplication<Application >().sendBroadcast(Intent (LOCATION_REFRESH ))
185173 }
0 commit comments