Skip to content

Commit 50702bd

Browse files
author
zhujiang2
committed
修改天气刷新时机,放到页面中进行加载
1 parent 28101e6 commit 50702bd

File tree

6 files changed

+50
-95
lines changed

6 files changed

+50
-95
lines changed

app/release/app-release.apk

-772 Bytes
Binary file not shown.

app/src/main/kotlin/com/zj/weather/view/weather/WeatherPage.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
1212
import androidx.compose.foundation.layout.navigationBarsPadding
1313
import androidx.compose.foundation.layout.padding
1414
import androidx.compose.foundation.layout.statusBarsPadding
15+
import androidx.compose.foundation.pager.PagerState
1516
import androidx.compose.runtime.Composable
17+
import androidx.compose.runtime.LaunchedEffect
1618
import androidx.compose.runtime.collectAsState
1719
import androidx.compose.runtime.getValue
1820
import androidx.compose.ui.Alignment
@@ -21,11 +23,13 @@ import androidx.compose.ui.platform.LocalConfiguration
2123
import androidx.compose.ui.platform.LocalContext
2224
import androidx.compose.ui.res.dimensionResource
2325
import androidx.compose.ui.tooling.preview.Preview
26+
import com.zj.model.PlayLoading
2427
import com.zj.model.WeatherModel
2528
import com.zj.model.air.AirNowBean
2629
import com.zj.model.room.entity.CityInfo
2730
import com.zj.model.weather.WeatherDailyBean
2831
import com.zj.model.weather.WeatherNowBean
32+
import com.zj.utils.XLog
2933
import com.zj.utils.lce.LcePage
3034
import com.zj.utils.view.ImageLoader
3135
import com.zj.utils.weather.IconUtils
@@ -35,6 +39,7 @@ import com.zj.weather.view.weather.widget.HeaderAction
3539
import com.zj.weather.view.weather.widget.HeaderWeather
3640
import com.zj.weather.view.weather.widget.WeatherAnimation
3741
import com.zj.weather.view.weather.widget.WeatherContent
42+
import kotlinx.coroutines.delay
3843

3944
@Composable
4045
fun WeatherPage(
@@ -46,19 +51,15 @@ fun WeatherPage(
4651
cityListClick: () -> Unit
4752
) {
4853
val context = LocalContext.current
49-
val weatherModel by weatherViewModel.weatherModel.collectAsState()
50-
val config = LocalConfiguration.current
54+
val weatherModel by weatherViewModel.weatherModel(cityInfo).collectAsState(PlayLoading)
55+
val isLand = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE
5156

5257
LcePage(playState = weatherModel, onErrorClick = onErrorClick) { weather ->
53-
Box(
54-
modifier = Modifier
55-
.fillMaxSize()
56-
) {
58+
Box(modifier = Modifier.fillMaxSize()) {
5759
ImageLoader(
5860
modifier = Modifier.fillMaxSize(),
5961
data = IconUtils.getWeatherBack(context, weather.nowBaseBean?.icon)
6062
)
61-
val isLand = config.orientation == Configuration.ORIENTATION_LANDSCAPE
6263
Row(
6364
modifier = Modifier
6465
.fillMaxWidth()
@@ -123,7 +124,6 @@ private fun HorizontalWeather(
123124
horizontalAlignment = Alignment.CenterHorizontally,
124125
verticalArrangement = Arrangement.Center,
125126
) {
126-
127127
// 天气头部
128128
HeaderWeather(
129129
cityInfo, weather.nowBaseBean, true, toCityMap = toCityMap

app/src/main/kotlin/com/zj/weather/view/weather/WeatherViewPager.kt

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@file:OptIn(ExperimentalFoundationApi::class)
1+
@file:OptIn(ExperimentalFoundationApi::class, ExperimentalFoundationApi::class)
22

33
package com.zj.weather.view.weather
44

@@ -27,7 +27,6 @@ import com.zj.utils.view.HorizontalPagerIndicator
2727
import com.zj.weather.permission.FeatureThatRequiresLocationPermissions
2828
import com.zj.weather.view.weather.viewmodel.WeatherViewModel
2929
import com.zj.weather.view.weather.widget.HeaderAction
30-
import kotlinx.coroutines.delay
3130

3231
@ExperimentalPermissionsApi
3332
@Composable
@@ -39,8 +38,8 @@ fun WeatherViewPager(
3938
) {
4039
val cityInfoList by weatherViewModel.cityInfoList.collectAsState(initial = arrayListOf())
4140
if (cityInfoList.isEmpty()) {
42-
FeatureThatRequiresLocationPermissions(weatherViewModel)
4341
NoCityContent(toWeatherList, toCityList)
42+
FeatureThatRequiresLocationPermissions(weatherViewModel)
4443
} else {
4544
val pagerState = rememberPagerState(
4645
initialPage = 0, initialPageOffsetFraction = 0f
@@ -50,7 +49,6 @@ fun WeatherViewPager(
5049
WeatherViewPager(
5150
weatherViewModel, cityInfoList, pagerState, toCityList, toCityMap, toWeatherList
5251
)
53-
CurrentPageEffect(pagerState, cityInfoList, weatherViewModel)
5452
Weather(cityInfoList, pagerState)
5553
}
5654
}
@@ -77,22 +75,6 @@ private fun Weather(
7775
}
7876
}
7977

80-
@Composable
81-
fun CurrentPageEffect(
82-
pagerState: PagerState, cityInfoList: List<CityInfo>, weatherViewModel: WeatherViewModel
83-
) {
84-
if (pagerState.isScrollInProgress) {
85-
return
86-
}
87-
val index = if (pagerState.currentPage > cityInfoList.size - 1) 0 else pagerState.currentPage
88-
LaunchedEffect(pagerState.currentPage) {
89-
delay(300L)
90-
val cityInfo = cityInfoList[index]
91-
weatherViewModel.getWeather(cityInfo)
92-
XLog.i("Query initialPage")
93-
}
94-
}
95-
9678
@Composable
9779
private fun NoCityContent(
9880
toWeatherList: () -> Unit,
@@ -135,7 +117,7 @@ fun WeatherViewPager(
135117
Box(
136118
modifier = Modifier.fillMaxSize()
137119
) {
138-
HorizontalPager(modifier = Modifier, state = pagerState, key = {
120+
HorizontalPager(modifier = Modifier, state = pagerState, beyondBoundsPageCount = 1, key = {
139121
try {
140122
cityInfoList[it].locationId
141123
} catch (e: Exception) {
@@ -148,12 +130,10 @@ fun WeatherViewPager(
148130
val pullRefreshState = rememberPullRefreshState(isRefreshing,
149131
{ weatherViewModel.refresh(cityInfoList[page]) })
150132

151-
Box(
152-
Modifier.pullRefresh(pullRefreshState)
153-
) {
133+
Box(Modifier.pullRefresh(pullRefreshState)) {
154134
WeatherPage(
155135
weatherViewModel, cityInfoList[page], onErrorClick = {
156-
weatherViewModel.getWeather(cityInfoList[page])
136+
weatherViewModel.weatherModel(cityInfoList[page])
157137
}, cityList = toCityList, toCityMap = toCityMap, cityListClick = toWeatherList
158138
)
159139

app/src/main/kotlin/com/zj/weather/view/weather/viewmodel/WeatherViewModel.kt

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,21 @@ import com.zj.model.room.entity.CityInfo
1515
import com.zj.model.weather.WeatherDailyBean
1616
import com.zj.model.weather.WeatherNowBean
1717
import com.zj.utils.XLog
18-
import com.zj.utils.checkCoroutines
1918
import com.zj.utils.checkNetConnect
2019
import com.zj.utils.view.showToast
2120
import com.zj.utils.weather.getLocationForCityInfo
2221
import com.zj.weather.R
2322
import com.zj.weather.widget.today.LOCATION_REFRESH
2423
import dagger.hilt.android.lifecycle.HiltViewModel
2524
import kotlinx.coroutines.Dispatchers
26-
import kotlinx.coroutines.Job
2725
import kotlinx.coroutines.async
2826
import kotlinx.coroutines.delay
2927
import kotlinx.coroutines.flow.Flow
3028
import kotlinx.coroutines.flow.MutableStateFlow
3129
import kotlinx.coroutines.flow.StateFlow
3230
import kotlinx.coroutines.flow.asStateFlow
31+
import kotlinx.coroutines.flow.channelFlow
3332
import kotlinx.coroutines.launch
34-
import kotlinx.coroutines.withContext
3533
import javax.inject.Inject
3634
import kotlin.collections.set
3735
import 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
}

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22
ext {
3-
extra["versionCode"] = 45
4-
extra["versionName"] = "4.5.3"
3+
extra["versionCode"] = 46
4+
extra["versionName"] = "4.5.4"
55

66
extra["sdkVersion"] = 34
77
extra["minSdkVersion"] = 24

utils/src/main/java/com/zj/utils/ContextUtils.kt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,6 @@ import android.content.Context
44
import android.net.ConnectivityManager
55
import android.net.NetworkCapabilities
66
import com.zj.model.Lang
7-
import kotlinx.coroutines.Job
8-
9-
10-
/**
11-
* 检查协程是否存在并运行
12-
*/
13-
fun Job?.checkCoroutines() {
14-
if (this?.isActive == true) return
15-
this?.cancel()
16-
XLog.d("Already in the query, first cancel the previous coroutine")
17-
}
187

198
/**
209
* 网络状态
@@ -34,13 +23,11 @@ fun Context.checkNetConnect(): Boolean {
3423

3524
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
3625
// 当前使用移动网络
37-
XLog.d("You are using a mobile network")
3826
true
3927
}
4028

4129
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
4230
// 当前使用WIFI网络
43-
XLog.d("The WIFI network is in use")
4431
true
4532
}
4633

0 commit comments

Comments
 (0)