Android Compose 新闻App(一)网络框架搭建

//LiveData、ViewModel

implementation ‘androidx.lifecycle:lifecycle-extensions:2.2.0’

implementation ‘androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1’

implementation ‘androidx.lifecycle:lifecycle-livedata-ktx:2.4.0-alpha02’

在这里插入图片描述

然后Sync Now。

三、数据API


现在免费的API数据接口实在太少了,聚合的每天免费次数也只供测试的,因为我重新找了一个API接口,就是天行数据,点击进入完成注册登录以及实名制。

然后我们可以进入我的控制台

在这里插入图片描述

点击这里申请接口,这里我选择了一个抗击疫情的接口,点击申请,可以看到这里有免费的调用次数,建议开发者使用自己的Key去调用。

在这里插入图片描述

下面回到我的控制台,然后是我申请的接口,找到抗击疫情,点击立即调试。

在这里插入图片描述

在这里可以看到请求地址和请求参数,我们点击测试请求按钮。

在这里插入图片描述

这里我们就拿到了返回的数据,通过返回的数据去构建Kotlin的Data类。

在这里插入图片描述

这里我推荐一个AS插件,很好用,点击File,然后Settings… ,选择Plugins,输入Generate Kotlin data classes from JSON

在这里插入图片描述

安装好插件之后,我们来使用它。在com.llw.goodnews包下新建一个bean包,鼠标右键点击Generate class from GSON。

在这里插入图片描述

输入数据类名称,然后将JSON格式数据粘贴到下方,点击OK。

在这里插入图片描述

生成了这么多个数据类,我们看一下EpidemicNews

在这里插入图片描述

它里面包裹了一个列表NewslistItem,你看到类都是这种情况,数据是很多的,所以每一层都有一个data类。现在数据有了,下面就是通过这个接口去进行网络请求了。

四、网络框架构建


做网络请求肯定不能够随便写,要考虑实用性,这个网络框架我也是在《第一行代码》中学到的,建议有些不知道的地方可以看看这本书,这里就拿来用,稍微有一点变化,不过不大。在com.llw.goodnews包下新建一个network包,包下新建一个ServiceCreator类,代码如下:

object ServiceCreator {

private const val baseUrl = “http://api.tianapi.com”

private fun getRetrofit() : Retrofit =

Retrofit.Builder()

.baseUrl(baseUrl)

.addConverterFactory(GsonConverterFactory.create())

.build()

fun create(serviceClass: Class): T = getRetrofit().create(serviceClass)

inline fun create(): T = create(T::class.java)

}

这里的代码就很简单了,通过网络地址构建一个Retrofit,然后根据传入的Service去访问接口,这里还有一个内联函数。

下面我们来构建这个服务接口,在此之前先在com.llw.goodnews包下新建一个utils包,包下新建一个Constant的类,里面的代码如下:

object Constant {

/**

  • 天行数据Key,请使用自己的Key

*/

const val API_KEY = “d8bc937c366fcd1629e00f19105db258”

/**

  • 请求接口成功状态码

*/

const val CODE = 200

/**

  • 请求接口成功状态描述

*/

const val SUCCESS = “success”

}

这里就是一个常量类,我们在请求API接口时会用到的一些不变的值就放这里。然后我们在network包下新建一个ApiService接口,代码如下:

interface ApiService {

/**

  • 获取新闻数据

*/

@GET(“/ncov/index?key=$API_KEY”)

fun getEpidemicNews(): Call

}

下面我们在network包下新建一个发起请求的NetworkRequest类,代码如下:

object NetworkRequest {

/**

  • 创建服务

*/

private val service = ServiceCreator.create(ApiService::class.java)

//通过await()函数将getNews()函数也声明成挂起函数。使用协程

suspend fun getEpidemicNews() = service.getEpidemicNews().await()

/**

  • Retrofit网络返回处理

*/

private suspend fun Call.await(): T = suspendCoroutine {

enqueue(object : Callback {

//正常返回

override fun onResponse(call: Call, response: Response) {

val body = response.body()

if (body != null) it.resume(body)

else it.resumeWithException(RuntimeException(“response body is null”))

}

//异常返回

override fun onFailure(call: Call, t: Throwable) {

it.resumeWithException(t)

}

})

}

}

这段代码解释一下:首先我们使用ServiceCreator创建了一个ApiService接口的动态代理对象,然后定义了一个getEpidemicNews函数,调用刚刚在ApiService中定义的getEpidemicNews方法,以发起疫情新闻数据请求。这里简化了Retrofit回调的写法,这里定义了一个await()函数,它是一个挂起函数,我们给它声明了一个泛型T,并将await()函数定义成了Call< T >的扩展函数,这样所有返回值是Call类型的Retrofit网络请求接口都可以直接调用await()函数了。

接着,await()函数中使用了suspendCoroutine函数来挂起当前协程,并且由于扩展函数的原因,我们现在拥有了Call对象的上下文,那么这里就可以直接调用enqueue()方法让Retrofit发起网络请求。

最后我们在存储库中发起数据请求,在com.llw.goodnews下创建一个repository包,包下新建一个BaseRepository,里面的代码如下:

open class BaseRepository {

fun fire(context: CoroutineContext, block: suspend () -> Result) =

liveData(context) {

val result = try {

block()

} catch (e: Exception) {

Result.failure(e)

}

//通知数据变化

emit(result)

}

}

这里的fire()函数,按照liveData()函数的参数接收标准定义的一个高阶函数。在fire()函数的内部会先调用一下liveData()函数,然后在liveData()函数的代码块中统一进行try catch处理,并在try语句中调用传入的Lambda表达式中的代码,最终Lambda表达式的执行结果并调用emit()方法发射出去。

然后我们在repository包下再新建一个EpidemicNewsRepository类,用于请求疫情新闻数据,继承自BaseRepository,里面的代码如下:

object EpidemicNewsRepository : BaseRepository() {

fun getEpidemicNews() = fire(Dispatchers.IO) {

val epidemicNews = NetworkRequest.getEpidemicNews()

if (epidemicNews.code == CODE) Result.success(epidemicNews)

else Result.failure(RuntimeException(“getNews response code is ${epidemicNews.code} msg is ${epidemicNews.msg}”))

}

}

这里我们调用父类的fire()函数,将liveData()函数的线程参数类型指定成了Dispatchers.IO,这样的代码块中的所有代码都是运行在子线程中,如果请求状态码是200,则表示成功,那么就使用Kotlin内置的Result.success()方法来包装获取的疫情新闻数据,然后就调用Result.failure()方法来包装一个异常信息。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

尾声

一转眼时间真的过的飞快。我们各奔东西,也各自踏上了自己的旅途,但是即使多年不见,也因为这份情谊我们依旧如从前那般“亲密”。不忘初心方得始终。加油吧,程序员们,在我看来35岁,40岁从来不是危机,只要永远不要忘记自己为何踏上征程!

为了让更多在学习中或者最近要准备面试的朋友们看到这篇文章,希望你们能多多评论,点赞+转发!

再次感谢所有给我提供过题目的朋友们,感谢一路有你!

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录*

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 47
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值