写点什么

flutter 之踩坑的日子(3)

用户头像
霜蓝手环
关注
发布于: 2020 年 09 月 24 日
flutter之踩坑的日子(3)

上回提到了有状态组件,但是并没有详细地展开。所以这次先将剩余的这点小尾巴收一收,然后再开始我们的项目之旅。



有状态组件由组件类和状态类组成,在组件类中需要重载_createState方法来实例化一个状态类对象。



这句话有点绕口,结合项目来看会好一些。



在示例项目中,我们的项目首先创建了一个无状态组件MyApp,然后在这个组件的build方法中,返回了一个 MaterialApp 对象。



这个对象中存在一个名为home的属性,通过它本身的注释可以得知,这个属性就是app的默认页面。



而这个页面,用代码来说,就是我们的



MyHomePage(title: "千里笔记"),



class MyHomePage extends StatefulWidget





MyHomePage是继承自StatefulWidge的类,它需要重载createState方法,来获得一个状态类。





@override



_MyHomePageState createState() => _MyHomePageState();





_MyHomePageState就是这个状态类的类型声明,_MyHomePageState()是该类型的实例化,等价于new _MyHomePageState() 。



这个状态类的构造方法build()需要返回一个Widget。示例项目返回的是Scaffold,这个组件是flutter提供的通用页面样式,可以包含顶部标题栏appBar,主体body和浮动按钮floatingActionButton。



我们依次查看这三个组件在项目中的作用。



appBar:AppBar(title:Text(widget.title))



这表示顶部标题栏使用传递进来的title值作为构造参数。我们也可以尝试使用其他的字符串,比如appBar:AppBar(title:Text(“flutter2020”)) ,然后保存代码。我们可以看到模拟器中的标题栏,其显示的标题也更改为flutter2020。

标题栏的样式,美化的事情现在不做。



这是flutter的hotReload机制,我们对代码的调整,无需重新生成和部署,就可以体现在模拟器中。这个机制用多了,就再也不想每次都重新编译下载啦。



主体body首先返回的是一个Center组件,这是一个处理定位的组件,在它之下的子组件,以居中的形式排列。它的子组件是Column,这个组件可以包含多个子组件,以自上而下的形式排列。



这些子组件需要被构造在Column组件的children中,children是一个存放组件的list。



        children: <Widget>[



          Text( 'You have pushed the button this many times:', ),



          Text( '按下 $_counter 次', style: Theme.of(context).textTheme.headline4,   ),



        ],



可以看出,这个Column中放置了2个Text组件,其中第2个Text组件中,使用了一个变量 $_counter ,这说明这个值是可以更改的。



这个变量被声明在状态类中,和它相关的还有一个类方法。



int _counter = 0;



void _incrementCounter() {



  setState(() {



    // This call to setState tells the Flutter framework that something has



    // changed in this State, which causes it to rerun the build method below



    // so that the display can reflect the updated values. If we changed



    // _counter without calling setState(), then the build method would not be



    // called again, and so nothing would appear to happen.



    _counter++;



  });



}



这里需要注意的是,下划线 “_“代表的是这个变量或者方法,是类本身的方法,可以被内部调用。



这个变量是一个int类型,而_incrementCounter() 方法则调用了setState方法,并在其中更改了_counter的值。



这个setState方法,作用就是更改状态类的状态。这个方法被调用,会导致相关的组件发生改变。可能是显示内容的变化,子组件的变化(添加、删除、更改)等等。这里涉及到flutter的更新机制,因为稍微考虑,就会发现在组件很多的时候,如果因为一个组件的微小改动,去重新绘制所有的组件,是一件消耗很大而且没有必要的事情。我们现在不深入探讨这个更新机制,先看看这个_incrementCounter() 方法在哪儿被调用。



    floatingActionButton: FloatingActionButton(



      onPressed: _incrementCounter,



      tooltip: '计数器',



      child: Icon(Icons.pages),



    ),



这个方法,被提供给floatingActionButton的构造参数onPressed。这个onPressed指向一个无返回值也无参数的函数。



综合来看,flutter的大体业务思路就比较清楚了。用无状态组件构造页面,处理布局和生成页面元素,使用组件的构造参数填充必要的参数值。对于需要动态更新的内容,用有状态组件的响应事件来处理用户操作。



OK,那么接下来进入正题。前文提到我们预备构造一个欢迎页面,这个欢迎页面的草图包含软件名。



当然了,只有软件名实在太过单薄,我预备在软件名下面加一行欢迎词。



这是对草案的合理调整和修改。



一点点微不足道的小改动。



当然,这点小改动应当反馈到界面草案上。



软件名我考虑使用图片,这样就可以用Image来处理。至于欢迎词,可以用Text来处理。



图片这玩意的调用方式有很多,本地读取,网络读取,资源读取都可以。经过初步测试,我发现使用资源读取的方式最为稳定



Image的资源调用方式是这样的:



1. 在pubsped.yaml中声明资源。



assets:



- images/footnote-welcome.png





2. 调用Image的asset方法来读取资源。



Image.asset("images/footnote-welcome.png"),





由于这个欢迎页面的内容构造后无需更改,所以我选用了无状态组件来构造这个页面。同时依然使用了脚手架组件来保证整体风格的一致。



注意,各组件之间的层级关系,可以在vscode中,方便地查看。调用左侧的flutter功能即可。



欢迎页面的组件层级关系图。





最终欢迎页面显示内容如下:





和草图相比,这个界面无疑更加高大上。



那么,今天就先到这里,下次我们再来整理这个页面的代码,看看这个页面具体都做了些什么。



发布于: 2020 年 09 月 24 日阅读数: 34
用户头像

霜蓝手环

关注

还未添加个人签名 2020.09.09 加入

还未添加个人简介

评论

发布
暂无评论
flutter之踩坑的日子(3)