下面回到我的控制台,然后是我申请的接口,找到抗击疫情,点击立即调试。
在这里可以看到请求地址和请求参数,我们点击测试请求按钮。
这里我们就拿到了返回的数据,通过返回的数据去构建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()方法来包装一个异常信息。
那么到这里为止,网络框架就搭建完成了,要使用的话还需要一些配置:
这里我们在com.llw.goodnews包下自定义一个App类,继承自Application,代码如下:
class App : Application() {
companion object {
@SuppressLint(“StaticFieldLeak”)
lateinit var context: Context
}
override fun onCreate() {
super.onCreate()
context = applicationContext
}
}
然后因为我们访问的API是http开头的,在Android9.0及以上版本中默认访问https,因此我们需要打开对http的网络访问,在res文件夹下新建一个xml文件夹,在xml文件夹下创建一个network_config.xml,里面的代码如下:
<?xml version="1.0" encoding="utf-8"?>然后我们在AndroidManifest.xml中去配置,如下图所示:
现在万事具备,只差请求了。
进入到MainActivity,新增如下代码:
EpidemicNewsRepository.getEpidemicNews().observe(this@MainActivity) { result ->
val epidemicNews = result.getOrNull()
if (epidemicNews != null) {
Log.d(“TAG”, “onCreate: ${epidemicNews.code}”)
Log.d(“TAG”, “onCreate: ${epidemicNews.msg}”)
Log.d(“TAG”, “onCreate: ${epidemicNews.newslist?.get(0)?.news?.get(0)?.title}”)
Log.d(“TAG”, “onCreate: ${epidemicNews.newslist?.get(0)?.news?.get(0)?.summary}”)
} else {
Log.e(“TAG”, “onCreate: null”)
}
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
最后
其实要轻松掌握很简单,要点就两个:
- 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
- 多练。 (视频优势是互动感强,容易集中注意力)
你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
阿里P7Android高级教程
下面资料部分截图,诚意满满:特别适合有3-5年开发经验的Android程序员们学习。
附送高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、近期面试跳槽、自身职业规划迷茫的朋友们。
Android核心高级技术PDF资料,BAT大厂面试真题解析;
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
阿里P7Android高级教程
下面资料部分截图,诚意满满:特别适合有3-5年开发经验的Android程序员们学习。
[外链图片转存中…(img-xavVoMFB-1712766655756)]
附送高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、近期面试跳槽、自身职业规划迷茫的朋友们。
Android核心高级技术PDF资料,BAT大厂面试真题解析;
[外链图片转存中…(img-645cKU4o-1712766655756)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-FglW4SGR-1712766655757)]