开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
继续《Android编程权威指南》第 24 章,本章应用叫 PhotoGallery,现在继续将应用实践完整。
三、从Flickr获取JSON数据
JSON(JavaScript Object Notation) 是由道格拉斯·克罗克福特构想和设计的一种轻量级资料交换格式。
Flickr 提供了方便而强大的 JSON API。现在,我们也根据书中推荐,注册个Flickr账户,打开它的开发文档。
Flickr 开发人员指南:www.flickr.com/services/de…
然后我们根据指南,先申请个非商用 API Key,再将我们的示例应用程式放入 App Garden 中。
然后我们会得到一个 API key,这个 key 比较长就不贴代码了,把它定义在一个单例中,我们继续在 FlickrApi 中新增接口方法,书中此接口指南地址:
@GET(
"services/rest/?method=flickr.interestingness.getList"
+ "&api_key=${FlickrConstants.FLICKR_KEY}"
+ "&format=json&nojsoncallback=1"
+ "&extras=url_s"
)
fun fetchPhotos(): Call<String>
这里根据同书中赋值参数。然后再去更新下 FlickrFetchr 类,这里我们就不像书中 Demo 一样修改方法了,我们新增一个方法,取名为 fetchPhotos(),然后调用 fetchPhotos 的 api,将我们原来 PhotoGalleryFragment 类中调用 fetchContent 的地方修改为调用 fetchPhotos。
最终运行项目,得到Log日志:
这里真是调了半天,去官网看了下 api ,跟书上提供的略有不同,还是需要参考最新的文档,不管怎么样,总算是有数据了,具体代码还是参考我的Github上的个人 Demo 啦。
- 接下来,新建 GalleryItem.kt 数据类进行接收请求数据:
data class GalleryItem(
var title:String="",
var id:String = "",
@SerializedName("url_s")
var url:String=""
)
然后就是对数据进行解析啦,将要用到Gson了。
可别忘记了在 build.gradle 中添加依赖啦:
implementation 'com.google.code.gson:gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
- 新建 PhotoResponse 类:
class PhotoResponse {
@SerializedName("photo")
lateinit var galleryItems:List<GalleryItem>
}
- 新建 FlickrResponse 类:
class FlickrResponse {
lateinit var photos: PhotoResponse
}
- 更新 fetchPhoto() 的返回类型:
@GET(
"services/rest/?method=flickr.interestingness.getList"
+ "&api_key=${FlickrConstants.FLICKR_KEY}"
+ "&format=json&nojsoncallback=1"
+ "&extras=url_s"
)
fun fetchPhotos(): Call<FlickrResponse>
-
更新 FlickrFetchr 中初始化 retrofit 的 addConverterFactory 为addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
-
更新 fetchPhotos() 方法:
fun fetchPhotos(): LiveData<List<GalleryItem>> {
val responseLiveData: MutableLiveData<List<GalleryItem>> = MutableLiveData()
val flickrHomePageRequest: Call<FlickrResponse> = flickrApi.fetchPhotos()
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)
}
})
return responseLiveData
}
这里会通过 filterNot 去过滤一下 url 为空的一些数据。这样后续给 recyclerview 提供数据集就不用再做空判断了。为后续工作稍微省点力。
- 更新 PhotoGalleryFragment 的 onCreate() 的内容为:
val flickrLiveData: LiveData<List<GalleryItem>> = FlickrFetchr().fetchPhotos()
flickrLiveData.observe(this,
Observer { gallerayItems ->
Log.d(TAG, "Response received:$gallerayItems")
})
运行日志:
此小节关于接口问题可能会遇到不少坑的,还是要多断点调试一下,仔细看看官方文档,分析下报错内容,还是可以解决的。可以调试下网页版的接口,看看网页是怎么调用具体的接口的。
参考:www.flickr.com/services/ap…
总之,最后还是调出来了,即使是照着书籍边学边敲代码,还是会遇到问题,然后再解决问题,感觉学到不少呢。
Flickr 貌似还挺不错的,是一家提供图片分享的网络相册,是Web 2.0的最佳利用例子之一。
其他
PhotoGallery 项目 Demo 地址:
🌈关注我吖~❤️
公众号:妮K妮K妮