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

基于Flutter构建小型新闻App

目录

1. 概述

1.1 功能概述

1.2 技术准备

1.3 源码地址

2. App首页

2.1 pubspec依赖

2.2 热门首页组件

2.2.1 DefaultTabController

2.2.2 Swiper

2.3 新闻API数据访问 

2.4 热门首页效果图

3. 新闻分类

3.1 GestureDetector

3.2 新闻分类效果图

4. 收藏功能

4.1 fluttertoast

4.2 shared_preferences

4.3 收藏效果图

5. 相关文档和总结


最近在研究基于Flutter构建一个简单的新闻资讯app,主要参考:用Flutter极速构建原生应用(需要电子书的话可以私聊),但是这本书有部分代码引用的组件版本已经不适用所以做了一些调整。以下是对于开发过程和遇到的一些问题的总结。

1. 概述

1.1 功能概述

对于Flutter的环境配置就不做总结了,为了节省时间大家可以用IntelliJ IDEA专业版,里面就可以创建Flutter项目。主要包含三个部分:

  • 热门新闻列表。
  • 分类新闻列表。
  • 新闻详情页。
  • 收藏功能。

1.2 技术准备

应用的首页用来展示热门新闻,我们可以选取天行数据的“综合新闻”接口服务,接口服务详细信息地址:综合新闻API接口 - 天行数据TianAPI。

在这注册一个账号用来做app测试。

然后创建一个Flutter应用,目录架构如下:

1.3 源码地址

项目源码:基于Flutter构建的新闻App。

Git地址:GitHub - BAStriver/flutter_test: test。

2. App首页

这里主要引用到DefaultTabController组件和Swiper组件。

  • 使用DefaultTabController组件来实现多模块的聚合页面。
  • 使用Swiper实现首页图片轮播。

首先在category和home文件夹下新建两个Dart文件,命名为category_view.dart与home_view.dart。目前实现如下效果:

2.1 pubspec依赖

如下是这个app的主要依赖设置:

dependencies:flutter:sdk: flutter# The following adds the Cupertino Icons font to your application.# Use with the CupertinoIcons class for iOS style icons.cupertino_icons: ^1.0.6http: ^1.1.2fluttertoast: ^8.2.4shared_preferences: ^2.2.2

2.2 热门首页组件

2.2.1 DefaultTabController

Widget _containerView(BuildContext context) {return Container(width: MediaQuery.of(context).size.width,height: MediaQuery.of(context).size.height,child: DefaultTabController(length: 2,child: Scaffold(appBar: AppBar(bottom: const TabBar(tabs: [Tab(child: Text("popular",style: TextStyle(color: Colors.black),),),Tab(child: Text("classifications",style: TextStyle(color: Colors.black),),)],indicatorColor: Colors.green,),title: const Text("ALl News",style: TextStyle(color: Colors.black),textAlign: TextAlign.center,),backgroundColor: Colors.white,actions: <Widget>[GestureDetector(child: Container(width: 60,child: const Icon(Icons.collections),),onTap: () {print('enter collection view.');Navigator.push(context, MaterialPageRoute(builder: (context) {print('enter collection view2.');return CollectionView();}));},)],),body: TabBarView(children: [HomeView(), CategoryView()],),)),);}

2.2.2 Swiper

Widget _buildSwiper(BuildContext context) {return Container(height: 150,child: Swiper(pagination: const SwiperPagination(),control: const SwiperControl(),autoplay: true,itemCount: 3,itemBuilder: (BuildContext context, int index) {return Container(margin: const EdgeInsets.only(bottom: 5),color: Colors.orange,width: MediaQuery.of(context).size.width,height: 150,child: Image.network(_dataList[_dataList.length - 1].picUrl,height: 150,width: MediaQuery.of(context).size.width,fit: BoxFit.fitWidth,),);},),);}

这里如果参考书上的写法会有问题,所以为了解决升级到Dart3.0后Swiper不兼容的问题可以参考:由于flutter_app依赖于flutter_swiper>=0.0.2,不支持零安全,版本解决失败。_because book depends on flutter_swiper >=0.0.2 whi-CSDN博客

2.3 新闻API数据访问 

Future<HomeModel> queryHomeData(int page) async {var url = Uri.parse('https://apis.tianapi.com/generalnews/index');var headers = <String, String>{"Access-Control-Allow-Origin": "*","Content-Type":"application/x-www-form-urlencoded"};var body = <String, String>{"key": URL_KEY, "num": "10", "page": "$page"};final response = await http.post(url,body: body, headers: headers);Map<String, dynamic> jsonMap = json.decode(response.body);return HomeModel.fromJson(jsonMap);}

这里会涉及到数据模型的构建和加载,可以参考:A value of type 'X' can't be assigned to a variable of type 'List' - 糯米PHP

2.4 热门首页效果图

3. 新闻分类

这里主要引用到GestureDetector组件。

关于新闻分类主页采用网格布局,根据天行数据网上提供的新闻接口定义10个分类。

final List<String> _categorys = ["GeneralNews","CarNews","DomesticNews","AnimeNews","FinancialNews","GameNews","InternationalNews","AINews","MilitaryNews","SportNews"];

3.1 GestureDetector

点击一个分类,页面会跳转到分类列表页。

关于详细的组件回调事件可以参考:

Flutter--GestureDetector手势识别组件_flutter gesturedetector-CSDN博客

Widget _getItem(BuildContext context, int index) {return Container(width: MediaQuery.of(context).size.width,height: 130,child: Row(children: <Widget>[GestureDetector(child: Container(width: MediaQuery.of(context).size.width / 2,color: index % 2 == 0 ? Colors.orange : Colors.blueAccent,height: 130,child: Center(child: Text(_categorys[index * 2],textAlign: TextAlign.center,style: const TextStyle(fontSize: 30, color: Colors.white),),),),onTap: () {Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {return CategoryListView(CATEGORY_KEYS[_categorys[index * 2]]!, _categorys[index * 2]);}));},),GestureDetector(child: Container(width: MediaQuery.of(context).size.width / 2,color: index % 2 == 0 ? Colors.blueAccent : Colors.orange,height: 130,child: Center(child: Text(_categorys[index * 2 +1],textAlign: TextAlign.center,style: const TextStyle(fontSize: 30, color: Colors.white),),),),onTap: () {Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {return CategoryListView(CATEGORY_KEYS[_categorys[index * 2 + 1]]!, _categorys[index * 2 + 1]);}));},)],),);}

3.2 新闻分类效果图

进入一般新闻的分类页面:

4. 收藏功能

这里主要引用了fluttertoast和shared_preferences组件。

  • fluttertoast实现弹窗效果。
  • shared_preferences实现本地缓存。

4.1 fluttertoast

实现弹窗是否收藏新闻。

Widget _buildItem(BuildContext context, int index) {return Container(height: 110,width: MediaQuery.of(context).size.width,margin: const EdgeInsets.only(bottom: 1),color: Colors.amber,child: GestureDetector(child: Row(children: <Widget>[Container(color: Colors.grey,child: Image.network(// "http://n.sinaimg.cn/sinakd202124s/162/w550h412/20210204/6706-kirmait9301473.jpg",_dataList[index].picUrl,width: 130,height: 110,fit: BoxFit.fitHeight,),),Column(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[Container(margin: const EdgeInsets.only(left: 10, top: 10, right: 10),width: MediaQuery.of(context).size.width - 130 - 20,child: Text(_dataList[index].title,overflow: TextOverflow.ellipsis,maxLines: 2,style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold),),),Container(margin: const EdgeInsets.only(left: 10, top: 5),child: Text(_dataList[index].description),),Container(margin: const EdgeInsets.only(left: 10, top: 5),child: Text(_dataList[index].ctime),),],)],),onLongPress: () {showDialog(context: context,builder: (BuildContext context) {return AlertDialog(title: Text('Do you want to save it ?'),actions: <Widget>[TextButton(onPressed: () {_addCollection(_dataList[index].id, _dataList[index].title);Navigator.of(context).pop();},child: Text('Yes')),TextButton(onPressed: () {Navigator.of(context).pop();},child: Text('No')),],);});},),);}

4.2 shared_preferences

实现本地缓存。

void _addCollection(String id, String title) async {print('id: ' + id);print('title: ' + title);SharedPreferences? preferences = await SharedPreferences.getInstance();String? data = preferences.getString(id);if (data == null) {await preferences.setString(id, title);Fluttertoast.showToast(msg: 'saved successfully.');} else {Fluttertoast.showToast(msg: 'the new already existing.');}}

4.3 收藏效果图

长按新闻。

收藏成功。

 

点击主页右上角的收藏图标进入收藏页面:

5. 相关文档和总结

开发体验初探 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

如何搭建flutter开发环境_flutter环境搭建-CSDN博客

Get 请求 | Post 请求 | 将响应结果转为 Dart 对象 | Future 异步调用

注:

1.遇到跨域问题访问不到图片可以参考:

开发环境如需解决跨域问题

flutter for web 带cookie的网络请求跨域问题处理

2.关于GestureDetector组件的用法可以参考:Flutter--GestureDetector手势识别组件

3.关于SharedPreferences组件的用法可以参考:Flutter 数据存储--shared_preferences使用详情

4.遇到:MissingPluginException (MissingPluginException(No implementation found for method... 需要重新启动项目。

5.遇到Navigator无法正常跳转页面时候可以参考:

Flutter无法跳转页面的解决方法(push方法无效) - 简书

Navigator的正确打开方式-CSDN博客

比如第4节开发收藏功能的时候遇到这个无法跳转的问题,main.dart做了如下的修改:

6.Flutter有两个App主题风格可以引用,包括:cupertino(IOS)、material(Android),具体的官方文档可以参考:Cupertino (iOS-style) widgets | Flutter 、Material Components widgets | Flutter。

关于这些风格的Widgets用法也可以参考:开启Fluter基础之旅<三>-------Material Design风格组件、Cupertino风格组件、Flutter页面布局篇...-CSDN博客

相关文章:

基于Flutter构建小型新闻App

目录 1. 概述 1.1 功能概述 1.2 技术准备 1.3 源码地址 2. App首页 2.1 pubspec依赖 2.2 热门首页组件 2.2.1 DefaultTabController 2.2.2 Swiper 2.3 新闻API数据访问 2.4 热门首页效果图 3. 新闻分类 3.1 GestureDetector 3.2 新闻分类效果图 4. 收藏功能 4…...

利用python将excel文件转成txt文件,再将txt文件上传hdfs,最后传入hive中

将excel文件转成txt文件&#xff0c;再将txt文件上传hdfs&#xff0c;最后传入hive中 注意的点 &#xff08;1&#xff09;先判断写入的txt文件是否存在&#xff0c;如果不存在就需要创建路径 &#xff08;2&#xff09;如果txt文件已经存在&#xff0c;那么先将对应的文件进行…...

【自学笔记】01Java基础-07面向对象基础-02继承

记录学习Java基础中有关继承、方法重写、构造器调用的基础知识&#xff0c;学习继承之前建议学习static关键字的内容【自学笔记】01Java基础-09Java关键字详解 1 继承概述 1.1 什么是继承&#xff1f; 1.2 继承的特点 子类可以继承父类的属性和行为&#xff0c;但是子类不能…...

二分查找(一)

算法原理 原理&#xff1a;当一个序列有“二段性”的时候&#xff0c;就可以使用二分查找算法。 适用范围&#xff1a;根据规律找一个点&#xff0c;能将这个数组分成两部分&#xff0c;根据规律能有选择性的舍去一部分&#xff0c;进而在另一个部分继续查找。 除了最普通的…...

【华为OD真题 Python】精准核酸检测

文章目录 题目描述输入描述输出描述示例1输入输出说明备注代码实现题目描述 为了达到新冠疫情精准防控的需要,为了避免全员核酸检测带来的浪费,需要精准圈定可能被感染的人群。 现在根据传染病流调以及大数据分析,得到了每个人之间在时间、空间上是否存在轨迹的交叉。 现…...

Springboot使用logback

文章目录 目录 文章目录 前言 一、添加依赖 二、使用步骤 三 、测试使用 总结 前言 Logback 是log4j 框架的作者开发的新一代日志框架&#xff0c;它效率更高、能够适应诸多的运行环境&#xff0c;同时天然支持 SLF4J。 Logback 的定制性更加灵活&#xff0c;同时也是 Sprin…...

【REST2SQL】03 GO读取JSON文件

REST2SQL需要一些配置信息&#xff0c;用JSON文件保存&#xff0c;比如config.json 1 创建config.json配置文件 {"hostPort":"localhost:5217","connString":"oracle://blma:5217127.0.0.1:1521/CQYH","_oracle":"ora…...

数据库-MySQL 启动方式

以管理员身份运行命令行 或者Shell net start //查看所有服务 net start MYSQL80 //启动服务 net stop MYSQL80 //停止服务完整安装MySQL社区版本的 会有这个 启动服务 停止服务 重启服务...

YAML使用

yaml yaml是类型aml&#xff0c;json的标记性语言&#xff0c;它强调以数据为中心 yaml的语法主要是如下几个&#xff1a; 大小写敏感 使用缩进表示层级关系 缩进不允许使用tab、只允许空格&#xff08;低版本限制&#xff0c;高版本不限制&#xff09; 缩进时空格数不重要&a…...

读书之深入理解ffmpeg_简单笔记2(初步)

再回看第一遍通读后的笔记&#xff0c;感觉还有很多的细节需要一一攻克,。 mp4的封装格式&#xff0c;解析方式。 flv的封装格式&#xff0c;解析方式。 ts的封装格式&#xff0c;解析方式。 第四章 封装和解封装 4.2 视频文件转flv &#xff08;头文件和文件内容&#xff0…...

ELK+kafka+filebeat企业内部日志分析系统搭建

看上面的拓扑图&#xff0c;我们至少准备七台机器进行下面的实验项目。 机器主要作用分布如下: 三台安装elasticsearch来搭建ES集群实现高可用&#xff0c;其他机器就依次安装filebeat,kafka,logstash和kibana软件 一、部署elasticsearch来搭建ES集群 1.安装jdk 由于ES运行…...

勒索检测能力升级,亚信安全发布《勒索家族和勒索事件监控报告》

评论员简评 近期(12.08-12.14)共发生勒索事件119起&#xff0c;相较之前呈现持平趋势。 与上周相比&#xff0c;近期仍然流行的勒索家族为lockbit3和8base。在涉及的勒索家族中&#xff0c;活跃程度Top5的勒索家族分别是&#xff1a;lockbit3、siegedsec、dragonforce、8base和…...

编译原理复习的有用链接

2024年1月7日&#xff0c;考完编译原理&#xff0c;是时候和考试时候的她说再见了&#xff0c;整理一些收藏夹里的链接和思考吧 实验看这里&#xff1a; 编译原理_HNU岳麓山大小姐的博客-CSDN博客 课后习题看这里&#xff1a; 编译原理作业答案github LL1文法复习 [编译原…...

不带控制器打包exe,转pdf文件时失败的原因

加了注释的两条代码后&#xff0c;控制器会显示一个docx转pdf的进度条。这个进度条需要控制器的实现&#xff0c;如果转exe不带控制器的话&#xff0c;当点击转换为pdf的按钮就会导致程序出错和闪退。 __init__.py文件的入口...

Python 注释的方法

在Python中&#xff0c;有两种常见的注释方法&#xff1a; 单行注释&#xff1a;使用#符号来注释一行代码。在#符号后面的内容将被视为注释&#xff0c;不会被解释器执行&#xff0c;如&#xff1a; # 这是一个单行注释 print(hello world!) # 打印字符串多行注释&#xff1…...

webman插件创建

webman插件创建 介绍 应用插件实际上是一个完整的应用&#xff0c;它能以插件的形式安装到主项目中&#xff0c;使主项目快速获得某个模块功能。 例如&#xff1a;主项目需要一个问答系统&#xff0c;则可以安装一个问答应用插件&#xff0c;需要一个商城系统&#xff0c;则安…...

大模型迎来“AppStore时刻”,OpenAI给2024的新想象

一夜之间&#xff0c;OpenAI公布了多个重磅消息&#xff0c;引发市场关注。 钛媒体App 1月5日消息&#xff0c;今晨&#xff0c;OpenAI公司向所有GPT开发者们发布一封邮件称&#xff0c;下周将上线自定义的“GPT Store”商店&#xff0c;这有望推动ChatGPT开发者生态不断完善。…...

ubuntu解决在pycharm上使用jupyter无法导入虚拟环境中的包的问题

ubuntu解决在pycharm上使用jupyter无法导入虚拟环境中的包的问题 根本原因是jupyter 没有和他对应的kernel 需要先使用命令行建立kernel 下载ipykernel pip install ipykernel 首先激活conda conda activate然后添加你的kernel到虚拟环境 python -m ipykernel install -…...

探索2024年软件测试的几大主导趋势

进入2024年&#xff0c;考虑影响测试环境的问题至关重要。这种思考将成为团队了解主要瓶颈和实现当今不断提高的期望的首要因素。 01 了解关键测试瓶颈 毋庸置疑&#xff0c;现代团队需要不断创新、适应和拥抱最新趋势&#xff0c;以保持竞争力并提供以客户为中心的解决方案。尽…...

Linux C语言 48-信号总结

Linux C语言 48-信号总结 本节关键字&#xff1a;Linux、C语言、常用信号 相关C库函数&#xff1a;printf、signal、kill Linux中都有哪些信号 信号在Linux操作系统中是很重要的&#xff0c;信号的产生方式可以是来自键盘、由软件条件产生、调用硬件异常产生。来自系统函数调…...

重塑机械键盘体验:ZMK固件的革新之旅与实践指南

重塑机械键盘体验&#xff1a;ZMK固件的革新之旅与实践指南 【免费下载链接】zmk ZMK Firmware Repository 项目地址: https://gitcode.com/gh_mirrors/zm/zmk 在机械键盘的世界里&#xff0c;固件如同键盘的灵魂&#xff0c;决定着它的响应速度、功能拓展性和个性化程度…...

XposedRimetHelper:如何优雅解决远程办公的定位打卡难题?[特殊字符]

XposedRimetHelper&#xff1a;如何优雅解决远程办公的定位打卡难题&#xff1f;&#x1f680; 【免费下载链接】XposedRimetHelper Xposed 钉钉辅助模块&#xff0c;暂时实现模拟位置。 项目地址: https://gitcode.com/gh_mirrors/xp/XposedRimetHelper 面对企业日益严…...

5个Rust驱动特性解决存储清理难题:Czkawka技术深度解析

5个Rust驱动特性解决存储清理难题&#xff1a;Czkawka技术深度解析 【免费下载链接】czkawka Multi functional app to find duplicates, empty folders, similar images etc. 项目地址: https://gitcode.com/GitHub_Trending/cz/czkawka Czkawka是一款基于Rust语言开发…...

Visio高效绘制神经网络卷积层:从基础到三维呈现

1. Visio绘制神经网络卷积层的入门指南 第一次用Visio画神经网络结构时&#xff0c;我盯着满屏的工具栏发懵——这玩意儿比Photoshop的图层还复杂。但摸索半天后发现&#xff0c;只要掌握几个核心功能&#xff0c;画卷积层其实比用PPT简单十倍。先说说最基础的形状选择&#xf…...

别再只用计数器了!手把手教你用Java实现滑动窗口限流(附完整可运行代码)

从零构建高精度滑动窗口限流器&#xff1a;Java实战与生产级优化 深夜的报警短信又一次震醒了你——核心API在整点时刻被突发流量冲垮。翻开监控图表&#xff0c;发现简单的计数器限流就像漏水的篮子&#xff0c;每到时间窗口切换的临界点&#xff0c;系统就会遭遇请求洪峰。这…...

Godot-MCP:如何通过双向语义桥梁解决游戏开发中的创意断层问题

Godot-MCP&#xff1a;如何通过双向语义桥梁解决游戏开发中的创意断层问题 【免费下载链接】Godot-MCP An MCP for Godot that lets you create and edit games in the Godot game engine with tools like Claude 项目地址: https://gitcode.com/gh_mirrors/god/Godot-MCP …...

YOLO12入门必看:从上传图片到JSON结果输出完整操作流程

YOLO12入门必看&#xff1a;从上传图片到JSON结果输出完整操作流程 1. 引言&#xff1a;为什么你需要了解YOLO12&#xff1f; 如果你正在寻找一个既快又准的目标检测工具&#xff0c;那么YOLO12的出现&#xff0c;可能就是你一直在等的那个答案。 想象一下这样的场景&#x…...

墨语灵犀助力软件测试:智能测试用例生成与缺陷报告分析

墨语灵犀助力软件测试&#xff1a;智能测试用例生成与缺陷报告分析 作为一名在软件测试领域摸爬滚打多年的工程师&#xff0c;我深知这份工作的“痛”与“乐”。痛的是&#xff0c;面对动辄几十上百页的需求文档&#xff0c;手动编写测试用例的枯燥与耗时&#xff1b;乐的是&a…...

从FamNet到通用计数:小样本学习如何让AI“数”遍万物

1. 小样本计数的革命&#xff1a;从专用工具到通用能力 记得我第一次接触物体计数任务时&#xff0c;用的还是专门针对人群计数的模型。当时为了统计商场人流量&#xff0c;不得不专门训练一个模型。后来遇到统计停车场的需求&#xff0c;又要重新收集数据训练新模型。这种&quo…...

Kimi-K2-W8A8量化版:推理精度反超官方!

Kimi-K2-W8A8量化版&#xff1a;推理精度反超官方&#xff01; 【免费下载链接】KIMI-k2-Thinking-W8A8-QuaRot 项目地址: https://ai.gitcode.com/Eco-Tech/KIMI-k2-Thinking-W8A8-QuaRot 导语&#xff1a;国内大模型量化技术再获突破——Kimi-K2-Thinking模型的W8A8量…...