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

973 阅读3分钟

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

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

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

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

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

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

Square 公司也为 Retrofit 提供了 Moshi 版数据类型转换器: github.com/square/retr…

找到一篇 Moshi 实践的文章,照着代码敲一遍熟悉熟悉。 blog.csdn.net/yuzhiqiang_…

当然,从 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<List<GalleryItem>> {
    val responseLiveData: MutableLiveData<List<GalleryItem>> = MutableLiveData()
    val flickrHomePageRequest: Call<FlickrResponse> = 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 实现依赖注入的地址可以参考官方文档:

developer.android.com/training/de…

其他

PhotoGallery 项目 Demo 地址:

github.com/visiongem/A…


🌈关注我吖~❤️

公众号:妮K妮K妮