实现功能:点击按钮让一个child
开始倒计时或者发送请求
难度:⭐⭐⭐⭐⭐
我们平时写项目基本也就是上面这些需求了,只要学会实现这些事件与数据传递,就可以轻松写出任何项目了。
使用回调传递事件
使用简单的回调就可以实现这几个需求,这也是整个flutter
的基础:如何改变一个state
内的数据,以及如何改变一个widget
的数据。
描述:一个
widget
收到事件后,改变child
显示的值
实现功能:点击加号让数字+1描述:一个
widget
在child
收到事件时,改变自己的值
实现功能:点击改变页面颜色描述:一个
widget
在child
收到事件时,触发自己的state
的方法
实现功能:点击发起网络请求,刷新当前页面
这几个都是毫无难度的,我们直接看同一段代码就行了
代码:
/// 这段代码是使用官方的代码修改的,通常情况下,只需要使用回调就能获取点击事件
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
int _counter = 0;
void _incrementCounter() {
// 在按钮的回调中,你可以设置数据与调用方法
// 在这里,让计数器+1后刷新页面
setState(() {
_counter++;
});
}
// setState后就会使用新的数据重新进行build
// flutter的build性能非常强,甚至支持每秒60次rebuild
// 所以不必过于担心触发build,但是要偶尔注意超大范围的build
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Text(
‘$_counter’,
style: Theme.of(context).textTheme.headline4,
),
),
floatingActionButton: _AddButton(
onAdd: _incrementCounter,
),
);
}
}
/// 一般会使用GestureDetector来获取点击事件
/// 因为官方的FloatingActionButton会自带样式,一般我们会自己写按钮样式
class _AddButton extends StatelessWidget {
final Function onAdd;
const _AddButton({Key key, this.onAdd}) : super(key: key);
@override
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: onAdd,
child: Icon(Icons.add),
);
}
}
这种方式十分的简单,只需要在回调中改变数据,再setState
就会触发build
方法,根据当前的数据重新build
当前widget
,这也是flutter
最基本的刷新方法。
在State中改变数据
在flutter
中,只有StatefulWidget
才具有state
,state
才具有传统意义上的生命周期(而不是页面),通过这些周期,可以做到一进入页面,就开始从服务器加载数据,也可以让一个Widget
自动播放动画
我们先看这个需求:
描述:一个
Widget
自己改变自己的值
实现功能:倒计时,从网络加载数据
这也是一个常见的需求,但是很多新手写到这里就不会写了,可能会错误的去使用FutureBuilder
进行网络请求,会造成每次都反复请求,实际上这里是必须使用StatefulWidget
的state
来储存请求返回信息的。
一般项目中,动画,倒计时,异步请求此类功能需要使用state
,其他大多数的功能并不需要存在state
。
例如这个widget
,会显示一个数字:
class _CounterText extends StatelessWidget {
final int count;
const _CounterText({Key key, this.count}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Text(‘$count’),
);
}
}
可以试着让widget从服务器加载这个数字:
class _CounterText extends StatefulWidget {
const _CounterText({Key key}) : super(key: key);
@override
__CounterTextState createState() => __CounterTextState();
}
class __CounterTextState extends State<_CounterText> {
@override
void initState() {
// 在initState中发出请求
_fetchData();
super.initState();
}
// 在数据加载之前,显示0
int count = 0;
// 加载数据,模拟一个异步,请求后刷新
Future _fetchData() async {
await Future.delayed(Duration(seconds: 1));
setState(() {
count = 10;
});
}
@override
Widget build(BuildContext context) {
return Center(
child: Text(‘$count’),
);
}
}
又或者,我们想让这个数字每秒都减1,最小到0。那么只需要把他变成stateful后,在initState中初始化一个timer,让数字减小:
class _CounterText extends StatefulWidget {
final int initCount;
const _CounterText({Key key, this.initCount:10}) : super(key: key);
@override
__CounterTextState createState() => __CounterTextState();
}
class __CounterTextState extends State<_CounterText> {
Timer _timer;
int count = 0;
@override
void initState() {
count = widget.initCount;
_timer = Timer.periodic(
Duration(seconds: 1),
(timer) {
if (count > 0) {
setState(() {
count–;
});
}
},
);
super.initState();
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Text(‘${widget.initCount}’),
);
}
}
这样我们就能看到这个widget
从输入的数字每秒减少1。
由此可见,widget
可以在state
中改变数据,这样我们在使用StatefulWidget
时,只需要给其初始数据,widget
会根据生命周期加载或改变数据。
在这里,我建议的用法是在Scaffold
中加载数据,每个页面都由一个Stateful
的Scaffold
和若干StatelessWidget
组成,由Scaffold
的State
管理所有数据,再刷新即可。
注意,即使这个页面的body是ListView
,也不推荐ListView
管理自己的state
,在当前state
维护数据的list
即可。使用ListView.builder
构建列表即可避免更新数组时,在页面上刷新列表的全部元素,保持高性能刷新。
在State中监听widget变化
描述:一个
Widget
自己的数据变化时,触发state
的方法
实现功能:一个在数据改变时播放过渡动画的组件
做这个之前,我们先看一个简单的需求:一行widget
,接受一个数字,数字是偶数时,距离左边24px
,奇数时距离左边60px
。
这个肯定很简单,我们直接StatelessWidget
就写出来了;
class _Row extends StatelessWidget {
final int number;
const _Row({
Key key,
this.number,
}) : super(key: key);
double get leftPadding => number % 2 == 1 ? 60.0 : 24.0;
@override
Widget build(BuildContext context) {
return Container(
height: 60,
width: double.infinity,
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(
left: leftPadding,
),
child: Text(‘$number’),
);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
最后
由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。
来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频**
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-2H4f61y6-1711074718857)]
最后
由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。
需要的朋友可以私信我【答案】或者点击这里免费领取