当前位置: 首页 > news >正文

android studio(NewsApiDemo)100%kotlin

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.dtcms.com/a/293592.html

      相关文章:

    1. 如何在 npm 上发布 Element Plus 二次封装组件
    2. Oracle 常用 SQL 命令集合
    3. 将 `knife4j` 和 `springdoc-openapi` 集成到你的 Spring Boot 应用
    4. 微软Fabric重塑数据管理:Forrester报告揭示高ROI
    5. 一次Oracle集群脑裂问题分析处理
    6. 前端实现类浏览器的 Ctrl+F 全局搜索功能(Vue2 + mark.js,用于Electron 、QT等没有浏览器Ctrl+F全局搜索功能的壳子中)
    7. Oracle迁移到高斯,查询字段默认小写,解决办法
    8. Qt 常用控件 - 1
    9. 分布式风电分散式风电
    10. Qt内存管理的核心点
    11. 技术速递|使用 Semantic Kernel 与 A2A 协议构建多智能体解决方案
    12. MCP:UVX的安装
    13. 计算机组成原理(一)
    14. 架构师--缓存场景
    15. 利用DeepSeek编写一个使用lzav算法的文件压缩工具
    16. 什么是LLMs.txt?如何在线生成?robots.txt一键转LLMs.txt
    17. 第九讲:C++中的list与forward_list
    18. OpenCV 零基础到项目实战 | DAY 2:图像预处理全解析
    19. 基于STM32驱动ADS1118实现电压采样并输出到串口
    20. PetaLinux 使用技巧与缓存配置
    21. 从零搭建 OpenCV 项目(新手向)-- 第二天 OpenCV图像预处理(一)
    22. 第四章 Freertos物联网实战DHT11温湿度模块
    23. 嵌入式学习-(李宏毅)机器学习(1)-day28
    24. 本地电脑映射端口到外网访问的开启方法和注意事项,内网服务提供跨网使用简单操作实现
    25. 神经网络和机器学习的一些基本概念
    26. 某种物联网SIM卡流量查询方法
    27. BQ4050RSMR DIOTEC高精度锂电池保护与电量监测芯片 集成保护+计量+通信
    28. 2025年Zigbee技术白皮书:全球物联网无线通信的关键创新
    29. 【Linux | 网络】应用层(HTTPS)
    30. 如何在 Ubuntu 20.04 Linux 上安装 TeamSpeak 客户端