《Android编程权威指南》之HTTP与后台任务(深入学习)

语言: CN / TW / HK

theme: cyanosis

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

继续《Android编程权威指南》第 24 章,开始深入学习了。

六、深入学习:其他JSON数据解析器和数据格式

这里主要介绍就是,Gson 不是唯一的 JSON 数据解析器。Square 公司还提供了另外一种 JSON 解析器叫 Moshi。

那么,既然我们要深入学习,就不仅仅只看一眼书中的概念啦,开始搜索一下 Moshi 吧,它的 Github 地址:https://github.com/square/moshi

从 Github 介绍就知道,Moshi 是适用于 Android、Java 和 Kotlin 的现代 JSON 库。 它使得将 JSON 解析为 Java 和 Kotlin 类变得容易。然而 Gson 的介绍就是说它是适用于 Java 的 JSON 解析库,因此,其实如果我们的应用,主 Kotlin 语言,又是使用的 Gson,就得多注意注意下解析问题了,网上我就搜到一篇,gson 反序列化成 data class 时的坑 具体自行看看文章啦。

Square 公司也为 Retrofit 提供了 Moshi 版数据类型转换器: https://github.com/square/retrofit/blob/master/retrofit-converters/moshi/README.md

找到一篇 Moshi 实践的文章,照着代码敲一遍熟悉熟悉。 https://blog.csdn.net/yuzhiqiang_1993/article/details/124076400

当然,从 Retrofit 的官方源码目录也可以看出,它还支持其他常见的数据格式。

image.png

真是强大额库呢。有得学啦!

七、深入学习:撤销网络请求

目前的 PhotoGallery 项目呢,是打开了它就会去进行网络请求,可是如果应用启动就快速回退,网络请求还是会继续执行,它并不会停止。这其实也是挺浪费资源的,虽然不会导致内存泄漏「因为FlickrFetchr 没有引用任何 UI 相关的组件,也没引用 ViewModel」,我们还是来继续优化下这个问题。

书中推荐的方式呢,就是把网络请求的 Call 对象保存起来,然后调用 Call.cancel() 撤销网络请求。撤销一个 Call 对象时,一个对应的 Callback.onFailure(...) 函数也会被调用。可以检查 Call.isCancelled 的值,判断 Callback 失败是不是因为撤销了网络请求(返回 true 值表示撤销成功)

  • 开始实践敲代码,新建 Repository.kt:

``` class Repository {

private lateinit var flickrCall: Call<FlickrResponse>

fun addFlickrCall(call: Call<FlickrResponse>) {
    flickrCall = call
}

fun cancelRequestInFlight() {
    if (::flickrCall.isInitialized) {
        flickrCall.cancel()
    }
}

} ```

  • 完善 PhotoGalleryViewModel.kt

``` class PhotoGalleryViewModel : ViewModel() {

private val repository = Repository()

val galleryItemLiveData: LiveData<List<GalleryItem>> = FlickrFetchr().fetchPhotos()

override fun onCleared() {
    super.onCleared()
    repository.cancelRequestInFlight()
}

} ```

  • 完善 FlickrFetchr

``` fun fetchPhotos(): LiveData> { val responseLiveData: MutableLiveData> = MutableLiveData() val flickrHomePageRequest: Call = flickrApi.fetchPhotos()

val repository = Repository()
repository.addFlickrCall(flickrHomePageRequest)

flickrHomePageRequest.enqueue(object : Callback<FlickrResponse> {
    override fun onResponse(call: Call<FlickrResponse>, response: Response<FlickrResponse>) {
        Log.d(TAG, "Response received : ${response.body()}")

        val flickrResponse: FlickrResponse? = response.body()
        val photoResponse: PhotoResponse? = flickrResponse?.photos
        var galleryItems: List<GalleryItem> = photoResponse?.galleryItems ?: mutableListOf()
        galleryItems = galleryItems.filterNot { it.url.isBlank() }
        responseLiveData.value = galleryItems
    }

    override fun onFailure(call: Call<FlickrResponse>, t: Throwable) {
        Log.e(TAG, "Failed to fetch photos", t)
        if (call.isCanceled){
            Log.e(TAG, "request Canceled")
        }
    }
})
return responseLiveData

} ```

八、深入学习:管理依赖

这里主要是说 FlickrFechr 对 FlickrApi 有依赖,然后再单元测试的时候,测试这两个类比较困难不方便。从而推出 Dependecy injection(DI) 设计模式,它可以把 FlickrApi 的代码逻辑中心化处理,即创建一个各个类都需要的依赖。

然后举了个例子,应用 DI 模式后,FlickrFetchr 代码大致为:

class FlickrFetchr(flickrApi: FlickrApi){ fun fetchContents():LiveData<String>{ ... } }

Android 平台中,Google 推荐的 DI 实现库是 Dagger2。

不过据我所知,不仅仅有 Dagger2,还有个 Hilt,将依赖注入场景化了,专门为 Android 开发提供。

关于 使用 Hilt 实现依赖注入的地址可以参考官方文档:

https://developer.android.com/training/dependency-injection/hilt-android?hl=zh-cn

其他

PhotoGallery 项目 Demo 地址:

github.com/visiongem/A…


🌈关注我吖~❤️

公众号:妮K妮K妮