0.首先导入相关的库
implementation
'com.squareup.retrofit2:retrofit:2.9.0'
implementation
'com.squareup.retrofit2:converter-gson:2.9.0'
implementation
'com.squareup.okhttp3:okhttp:4.8.0' // 导入第一行之后如果未成功导入okhttp库,手动导入,retrofit 是基于okhttp库进行封装的。
1.定义一个 Service 接口
interface PlaceService
{//发起请求
@GET
("v2/place") // 调用此方法时会发起一条GET请求
suspend fun getData
(@Query
("query") query: String, //自动开启子线程
@Query
("token") token: String,
@Query
("lang") lang: String
):DailyResponse
}
2.定义一个 ServiceCreator 单例类,用于生成 动态代理对象
object ServiceCreator
{
val retrofit
= Retrofit.Builder
()
.baseUrl
("https://api.caiyunapp.com/")
.addConverterFactory
(GsonConverterFactory.create
())
.build
()
//创建动态代理对象,inline 内联函数使泛型不会擦除,reified关键字表明泛型要进行实化
inline fun
<reified T
> create
() = retrofit.create
(T::class.java
)
}
3.定义一个 Network 单例类,用于提供网络请求的接口
object WeatherNetwork
{
private val placeService
= ServiceCreator.create
<PlaceService
>()
//内部开启一个新的IO线程
suspend fun getPlace
(name: String
) = placeService.getData
(name,WeatherApplication.token,
"zh_CN")
}
4.定义一个data class 用于接收数据
data class DailyResponse
(val status: String, val result: Result
) {//data类对数据做了一个很好的封装
data class Result
(val daily: Daily
)
data class Daily
(val astro: List
<Astro
>, val temperature: List
<Temperature
>, val skycon: List
<Skycon
>)
data class Astro
(val sunrise: Sunrise, val sunset: Sunset
)
data class Sunrise
(val time: String
)
data class Sunset
(val time: String
)
data class Temperature
(val max: Float, val min: Float
)
data class Skycon
(val date: Date, val value: String
)
}
基于官方推荐的架构
0.View 从ViewModel 中获得数据
ViewMdel 中定义两个 LiveData ,第一个 LiveData的值改变时触发 switchMap() 函数,生成第二个LiveData 对象。
class HotViewModel
: ViewModel
() {
private var pageLiveData
= MutableLiveData
<Int
>()
fun queryArticle
(page: Int
) {
pageLiveData.value
= page
}
// 当 pageLivedata 改变时触发 switchMap
() 函数,返回一个liveData
val articleLiveData
= Transformations.switchMap
(pageLiveData
) {
page -
>
HotRepository.getArticle
(page
)
}
}
1.ViewModel 从 Repository 中获取数据
Repository 可以提供本地数据,或者网络数据。
object HotRepository
{
fun getArticle
(page: Int
) = liveData
{ // livedata
() 函数拥有协程作用域,同时返回LiveData对象
val res
= try
{
val articleResponse
= ArticleNetwork.getArticle
(page
)
if (articleResponse.errorCode
== 0
) {
Result.success
(articleResponse
) // Result 类可以对结果进行封装,返回更加直观的信息
} else {
Result.failure
(RuntimeException
("errorCode is ${articleResponse.errorCode}"))
}
} catch
(e: Exception
) {
Result.failure
<ArticleResponse
>(e
)
}
emit
(res
)
}
}