api接口地址:https://newsapi.org/docs/get-started

项目成品地址:https://github.com/RushHan824/NewsApiDemo

项目效果展示:

 MVVM数据流

 UML图


本系列文章将带你从零实现一个新闻列表App,适合零基础读者。一步步来,力求让每个人都能跟着做出来。

第一步:分析API和JSON,写好数据类。

1. 打开API网址,获取返回的JSON数据。

        

2. 观察JSON结构,分析每个字段。

        这里注意会有null的字段 所以kotlin中创建变量的时候需要注意

3. 用Kotlin写出对应的数据类,为后续网络请求和数据展示打好基础。

        创建一个数据类 data class

        然后根据上图的json结构 把数据类一层一层构建出来 还是比较简单的 结果如下图

        当然要注意上面说到的null字段问题 而kotlin中val搭配问好?比较好

                比如:val title: String? 就表示可能会null 安全且规范


第二步:配置Retrofit,完成网络请求

        1.添加依赖

                在build.gradle中添加Retrofit和Gson等依赖。

                如下图 注意是app的.gradle文件 依赖可以一起添加了

//实现网络请求的第一步:加上retrofit和gson的依赖implementation("com.squareup.retrofit2:retrofit:2.9.0")implementation("com.squareup.retrofit2:converter-gson:2.9.0")//livedata viewmodel依赖implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2")//Glide 图片加载implementation("com.github.bumptech.glide:glide:4.16.0")annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")

        2.定义api接口

                创建接口,声明请求方法和返回类型。

interface Top_ApiService {@GET("top-headlines")suspend fun get_topNews(@Query("country") country: String,@Query("apiKey") apiKey: String):News_Items
}
//我们访问一个网页需要网址 组成可以是baseurl+路径+参数
//这里@GET就是一种请求方式 表示从网页里拿数据 括号里"top-headlines"可以表示具体的路径
//suspend挂起 和kotlin中协程一起搭配 不会阻塞主线程 执行网络请求这样的耗时操作的时候 可以避免界面卡顿
//接下去两个Query就是两个参数
//最后返回类型是数据类
//返回类型通常是我们根据JSON结构定义的数据类(如News_Items),Retrofit会自动帮我们把JSON解析成这个类的对象

        3.配置RetrofitClient                

object RetrofitClient {//object关键字声明了一个单例对象 这样RetrofitClient在全局只有一个实例 方便全局调用 不用每次都新建private val client = OkHttpClient.Builder()//OkHttpClient 是Retrofit底层用来发网络请求的库.addInterceptor(Interceptor { chain ->val request = chain.request().newBuilder().header("User-Agent", "Mozilla/5.0 (Android)").build()chain.proceed(request)//表示继续执行请求})//这里用Builder()自定义了一个OkHttpClient 加了一个拦截器Interceptor//拦截器可以在请求发出前、响应返回后做一些统一处理//这里的拦截器给每个请求都加上了一个User-Agent请求头(模拟浏览器或App身份,有些API会校验这个) 对于现在用的api 不加这个拦截器不行.build()val api: Top_ApiService by lazy {//懒加载的属性 只有第一次用到时才会初始化 节省资源Retrofit.Builder().baseUrl("https://newsapi.org/v2/")//设置api基础网址.addConverterFactory(GsonConverterFactory.create())//用gson把json自动转换成kotlin对象.client(client).build()//创建retrofit对象.create(Top_ApiService::class.java)//创建API接口的实现对象}
}

第三步:MVVM架构与数据流转

        1.Repository层

class Repository(private val api: Top_ApiService){//数据仓库//作用是在这里写一下api调用方法的具体实现suspend fun getTopNews(country: String,apiKey: String):News_Items{return api.get_topNews(country,apiKey)}
}
//在MVVM架构中 Repository负责从网络或本地数据库获取数据 并将数据提供给ViewModel 这样可以让ViewModel只关注数据的展示逻辑 而不用关心数据是怎么来的
//getTopNews方法:调用API接口获取新闻数据,参数和返回值都和API接口保持一致。用suspend修饰,表示要在协程中调用,避免阻塞主线程

            2.ViewModel层

    class NewsViewModel(private val repository: Repository):ViewModel(){private val _newsList = MutableLiveData<News_Items>()val newsList:LiveData<News_Items> = _newsListfun fetchTopNews(country:String,apikey:String){viewModelScope.launch{try{val result=repository.getTopNews(country,apikey)_newsList.value=result}catch(_:Exception){ }}}
    }
    //ViewModel:用于管理界面数据,保证数据在界面旋转等情况下不会丢失。
    //      比如你在看新闻列表,突然手机横屏了,Activity会被销毁再重建。
    //      如果你把数据直接写在Activity里,界面重建后,数据会丢失,需要重新请求。
    //ViewModel的作用就是:即使界面重建,ViewModel里的数据还在,不会丢失,这样用户体验更好。//LiveData/MutableLiveData:实现数据的观察者模式,界面可以自动感知数据变化并刷新。
    //viewModelScope.launch:在ViewModel自带的协程作用域中启动协程,进行异步操作(如网络请求),不会阻塞主线程。
    //异常捕获:防止网络请求失败导致程序崩溃,可以在catch里加上错误提示

              3.Activity层            

      class NewsFeedActivity : AppCompatActivity() {private lateinit var viewModel: NewsViewModelprivate lateinit var adapter: NewsAdapteroverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_news_feed)val recyclerView = findViewById<RecyclerView>(R.id.newsRecyclerView)recyclerView.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)//设置布局管理器 瀑布流adapter = NewsAdapter()//创建适配器recyclerView.adapter = adapter//绑定适配器val repository = Repository(RetrofitClient.api)//创建数据仓库对象viewModel = NewsViewModel(repository)//延迟初始化viewmodelviewModel.newsList.observe(this) { newsItems ->adapter.submitList(newsItems.articles)}
      //        通过 observe 订阅 newsList 数据
      //        当新闻数据发生变化时 自动调用 lambda 表达式 把新数据提交给 Adapter 刷新界面viewModel.fetchTopNews("us", "08928b7fed414010820d9af990c05f89")}
      }

      第四步:RecyclerView展示新闻列表

              1.编写Adapter

      class NewsAdapter : RecyclerView.Adapter<NewsAdapter.NewsViewHolder>() {private var articles: List<Article> = emptyList()fun submitList(list: List<Article>) {//提交articles = listnotifyDataSetChanged()//通知recyclerview 数据发生变化 刷新一下}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsViewHolder {val view = LayoutInflater.from(parent.context).inflate(R.layout.item_news, parent, false)return NewsViewHolder(view)}//复制粘贴override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {holder.bind(articles[position])}//当前位置数据绑定override fun getItemCount(): Int = articles.size//告诉recyclerview有多少条数据class NewsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {//private val titleTextView: TextView = itemView.findViewById(R.id.newsTitle)private val imageView: ImageView = itemView.findViewById(R.id.newsImage)fun bind(article: Article) {//将article数据绑定到控件上titleTextView.text = article.titleGlide.with(itemView.context).load(article.urlToImage).into(imageView)//Glide高效加载网络图片,防止界面卡顿}}
      }//NewsAdapter:是 RecyclerView 的“桥梁”,负责把新闻数据展示到每一行 item 上
      //onCreateViewHolder:每当需要一个新的 item 行时,加载 item_news.xml 布局,生成 ViewHolder
      //onBindViewHolder:把对应位置的数据绑定到 ViewHolder 上
      //NewsViewHolder:用来缓存和管理 item_news.xml 里的控件,避免重复查找

          2.编写item布局

      本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
      如若转载,请注明出处:http://www.pswp.cn/bicheng/90307.shtml
      繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90307.shtml
      英文地址,请注明出处:http://en.pswp.cn/bicheng/90307.shtml

      如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

      相关文章

      面试高频题 力扣 417. 太平洋大西洋水流问题 洪水灌溉(FloodFill) 深度优先遍历(dfs) 暴力搜索 C++解题思路 每日一题

      目录零、题目描述&#xff1a;用人话再讲一遍一、为什么这道题值得咱们学习&#xff1f;二、思路探索常规思路&#xff1a;逐个检查每个格子&#xff08;会超时&#xff01;⚠️&#xff09;三、正难则反&#xff1a;反向思维的巧妙应用 &#x1f504;&#xff08;思考时间&…

      博物馆智慧导览系统AR交互与自动感应技术:从虚实融合到智能讲解的技术实践

      本文面向博物馆信息化开发者、智慧场馆系统技术建设师及AR 设计工程师,从AR 交互与自动感应技术的逻辑出发,拆解AR虚实融合技术与智能讲解自动感应技术的原理&#xff0c;为相关开发者实践提供可复用的技术路径。如需获取博物馆智慧导览系统解决方案请前往文章最下方获取&#…

      高效编程革命:DeepSeek V3多语言支持与性能优化实战

      文章目录 如何利用DeepSeek V3编写高效程序代码:从原理到实践 引言 一、DeepSeek V3核心能力解析 1.1 模型架构与优势 1.2 与传统编程辅助工具对比 二、高效代码编写实践指南 2.1 精准提示工程(Prompt Engineering) 基础提示模板 高级提示技巧 2.2 生产级代码生成案例 示例:…

      OkHttp 与 JSON 解析库完美结合:Moshi/Jackson/Gson 实战指南

      前言在现代 Android 开发中&#xff0c;网络请求与 JSON 数据处理是密不可分的。OkHttp 作为强大的 HTTP 客户端&#xff0c;与 JSON 解析库&#xff08;Moshi/Jackson/Gson&#xff09;的结合使用&#xff0c;可以极大简化网络请求与数据解析的流程。本文将详细介绍如何将 OkH…

      An error occurred at line: 1 in the generated java file问题处理及tomcat指定对应的jdk运行

      一、背景 tomcat7启动后&#xff0c;加载jsp页面报错&#xff0c;提示无法将jsp编译为class文件&#xff0c;主要报错信息如下&#xff1a; An error occurred at line: 1 in the generated java file 最后确认该错误原因为&#xff1a;tomcat7不支持jdk1.8版本 机器上已配…

      深入剖析大模型在文本生成式 AI 产品架构中的核心地位

      一、大模型的崛起与概念解析 在人工智能技术飞速迭代的当下&#xff0c;大模型已成为驱动行业发展的核心引擎。从技术定义来看&#xff0c;大模型&#xff08;Large Model&#xff09; 是指基于深度学习架构、具备海量参数规模&#xff08;通常数十亿至数万亿级别&#xff09;&…

      Vue Scoped样式:当动态元素成为“无家可归“的孤儿

      引言&#xff1a;一场CSS的"身份危机"想象一下&#xff1a;你精心设计了一个Vue组件&#xff0c;为每个元素添加了漂亮的样式。你满意地添加了scoped属性&#xff0c;确保样式不会"越狱"影响其他组件。然后你动态添加了一些新元素&#xff0c;却发现它们完…

      vmware分配了ubuntu空间但是ubuntu没有获取

      一开始我看vmware中的ubuntu磁盘空间只有200g不够用&#xff0c;我在vmware给Ubuntu分了300G的磁盘空间&#xff0c;但是ubuntu还是只有之前的200g 如图在ubuntu查看后来发现&#xff0c;在磁盘软件里面需要自己分配磁盘空间大小拓展后就可以了

      [MarkdownGithub] 使用块引用高亮显示“注意“和“警告“和其他注意方式的选项

      参考来源: https://github.com/orgs/community/discussions/16925 Alerts are an extension of Markdown used to emphasize critical information. On GitHub, they are displayed with distinctive colors and icons to indicate the importance of the content. 提示框是 Ma…

      mac测试ollama llamaindex

      LlamaIndexs 将大语言模型和外部数据连接在一起的工具。大模型prompt有一个长度限制&#xff0c;当外部知识的内容超过这个长度&#xff0c;无法同时将有效信息传递给大模型&#xff0c;因此就诞生了 LlamaIndex。 具体操作就是通过多轮对话的方式不断提纯外部数据&#xff0c…

      数据结构:字符串:大小写转换(changing case of a string)

      目录 第一性问题&#xff1a;什么是“大小写”&#xff1f; 逐步构造代码&#xff1a;全部转为大写 我们现在用 第一性原理 的方式&#xff0c;从字符串与字符的本质出发&#xff0c;一步步推导出如何在 C 语言中将字符串中的字母变成全部大写或全部小写。 第一性问题&…

      闲庭信步使用图像验证平台加速FPGA的开发:第三十二课——车牌识别的FPGA实现(4)车牌字符的分割定位

      &#xff08;本系列只需要modelsim即可完成数字图像的处理&#xff0c;每个工程都搭建了全自动化的仿真环境&#xff0c;只需要双击top_tb.bat文件就可以完成整个的仿真&#xff0c;大大降低了初学者的门槛&#xff01;&#xff01;&#xff01;&#xff01;如需要该系列的工程…

      03_java_运行机制

      1. java执行流程2. 什么是编译3. 什么是运行

      鸿蒙卡片开发保姆级教程

      卡片 1. 卡片概念 什么是卡片&#xff1f;卡片用来显示或者提示一些基本信息或者进行一些基本操作。注意不能做重逻辑&#xff0c;所有重要逻辑全部交给应用如果是元服务如何唤醒&#xff1f;因为元服务不提供桌面应用图标&#xff0c;我们可以通过用户手动的方式在桌面上添加一…

      反向传播及优化器

      反向传播&#xff08;Backpropagation&#xff09;反向传播是计算梯度的算法&#xff0c;核心作用是高效求解 “损失函数对模型所有参数的偏导数”&#xff08;即梯度&#xff09;。没有反向传播&#xff0c;深度学习的大规模训练几乎不可能实现。 整个过程像 “从终点回溯到起…

      【机器学习深度学习】生成式模型的评估与验证

      目录 前言 1. 主观评估&#xff1a;以人为本的质量判断 1.1 什么是主观评估&#xff1f; 1.2 主观评估的核心流程 1.3 主观评估的优缺点 2. 客观评估&#xff1a;量化的性能衡量 2.1 什么是客观评估&#xff1f; 2.2 常见的客观评估指标 文本生成 图像生成 多模态生…

      Linux文件——Ext2文件系统(3)_软硬链接

      文章目录文件的软硬链接软链接硬链接软硬链接对比软硬链接应用软硬链接注意事项总结文件的软硬链接 本篇文章将重点讲解文件系统中的一个重要的知识点&#xff1a; 即文件的软硬链接。 软链接 对于软链接的讲解&#xff0c;我们先来使用一个指令看看效果&#xff1a;ln -s 被…

      Java SE:类与对象的认识

      Java中的类与对象&#xff1a;构建程序世界的基石 在Java编程的世界里&#xff0c;类与对象是面向对象编程&#xff08;OOP&#xff09;的核心概念&#xff0c;它们就像构建大厦的砖瓦&#xff0c;支撑起整个程序的结构。理解类与对象&#xff0c;是掌握Java编程的关键一步。 类…

      Hexo - 免费搭建个人博客03 - 将个人博客托管到github,个人博客公开给大家访问

      导言我的博客&#xff1a;https://q164129345.github.io/ 既然要将个人博客托管到github&#xff0c;首先我们肯定要有一个github账户。另外也需要在电脑上安装另外一个著名的代码管理工具git。 一、创建github仓库二、在Hexo设置部署的内容# Deployment## Docs: https://hexo.…

      一次Oracle集群脑裂问题分析处理

      问题描述 填写问题的基础信息。 系统名称 数据库集群 IP地址 xxxxxx 操作系统 Linux 数据库 Oracle 11.2.0.4 症状表现 问题的症状表现如下 4月26号晚22点02分左右&#xff0c;HIS集群发生脑裂&#xff0c;十几分钟后&#xff08;22.18&#xff09;一节点集群率先获…