Flutter学习(五)开发初体验

2020-04-01  本文已影响0人  yanhooIT

内部团队学习,以简单直接为主

创建Flutter项目

cd 指定目录
// 创建Flutter项目
flutter create hello_flutter

项目文件介绍

工程目录

runApp和Widget

// 启动App
void main() => runApp(MyApp());

/// 是Flutter内部提供的一个函数
/// 当我们启动一个Flutter应用程序时就是从调用这个函数开始的
/// 入参是一个Widget
void runApp(Widget app) {
  // 省略代码...
}
import 'package:flutter/material.dart';

material设计风格

自定义Widget来解决Flutter嵌套过多的问题

class MyStatelessWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return <返回我们的Widget要渲染的Widget,比如一个Text Widget>;
  }
}

为什么定义到Widget中的数据一定是不可变的,需要使用final来修饰

@immutable
abstract class Widget extends DiagnosticableTree {
    // 省略代码...
}

StatelessWidget

/// 导入Flutter提供的Material库,可以使用其中很多内置Widget
import 'package:flutter/material.dart';

/// runApp是Flutter内部提供的一个函数
/// 当我们启动一个Flutter应用程序时就是从调用这个函数开始的
/// 入参是一个Widget
void main() => runApp(MyApp());

/// 自定义Widget来减少嵌套层级
class MyApp extends StatelessWidget {
  /// 继承自StatelessWidget必须实现此方法
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      /// 去除debug标记
      debugShowCheckedModeBanner: false,
      /// 设置主题
      theme: ThemeData(primaryColor: Colors.yellowAccent),
      /// Scaffold是脚手架
      home: Scaffold(
        /// 导航栏
        appBar: AppBar(
          title: Text("火信"),
        ),
        /// body是页面的内容部分
        body: HomeView(),
      ),
    );
  }
}

/// 自定义Widget - 首页Widget
class HomeView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    /// 界面整体边距
    return Padding(
      /// padding属性用于设置边距大小
      padding: const EdgeInsets.all(8.0),
      /// 如果这里使用Column会出错
      /// 因为在Flutter的布局中,内容是不能超出屏幕范围的,当超出时不会自动变成滚动效果,而是会报下面的错误
      ///
      /// 解决方案:Column换成ListView
      /// ListView可以让自己的子Widget变成滚动的效果
      child: ListView(
        children: <Widget>[
          ProductCell("火信1.0", "来火信,聊懂区块链",
              "https://bkimg.cdn.bcebos.com/pic/09fa513d269759ee3c61708ebffb43166d22df45?x-bce-process=image/watermark,g_7,image_d2F0ZXIvYmFpa2U4MA==,xp_5,yp_5"),
          ProductCell("火信2.0", "来火信,聊懂区块链",
              "https://bkimg.cdn.bcebos.com/pic/09fa513d269759ee3c61708ebffb43166d22df45?x-bce-process=image/watermark,g_7,image_d2F0ZXIvYmFpa2U4MA==,xp_5,yp_5"),
          ProductCell("火信3.0", "来火信,聊懂区块链",
              "https://bkimg.cdn.bcebos.com/pic/09fa513d269759ee3c61708ebffb43166d22df45?x-bce-process=image/watermark,g_7,image_d2F0ZXIvYmFpa2U4MA==,xp_5,yp_5"),
        ],
      ),
    );
  }
}

/// 自定义Widget - 单个Cell Widget
class ProductCell extends StatelessWidget {
  final String title;
  final String desc;
  final String imageUrl;
  
  /// 构造函数
  ProductCell(this.title, this.desc, this.imageUrl);

  @override
  Widget build(BuildContext context) {
    /// Container用于设置内边距和边框
    return Container(
      padding: EdgeInsets.all(20),
      /// 通过decoration来设置边框
      decoration: BoxDecoration(border: Border.all()),
      child: Column(
        children: <Widget>[
          /// Text文本Widget
          Text(title, style: TextStyle(fontSize: 24)),
          Text(desc, style: TextStyle(fontSize: 18)),
          /// 文字图片的间距
          SizedBox(
            /// 设置一个height属性,可以增加一些距离
            height: 10,
          ),
          /// Image是图片Widget
          Image.network(imageUrl)
        ],
      ),
    );
  }
}

StatefulWidget

/// 导入Flutter提供的Material库,可以使用其中很多内置Widget
import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    /// MaterialApp提示区分大小写
    return MaterialApp(
      /// 去除debug标记
//      debugShowCheckedModeBanner: false,
      /// 设置主题
      theme: ThemeData(primaryColor: Colors.yellowAccent),
      home: HomeWidget(),
    );
  }
}

class HomeWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    /// Scaffold是脚手架,区分大小写
    return Scaffold(
      /// Scaffold提示区分大小写
      appBar: AppBar(
        title: Text("HuobiChat"),
      ),
      body: HomeView("你好,火信!"),
    );
  }
}

/// Widget是不加_: 暴露给外部使用
class HomeView extends StatefulWidget {
  final String message;

  HomeView(this.message);

  @override
  State<StatefulWidget> createState() {
    return _HomeViewState();
  }
}

/// 为什么Flutter在设计的时候StatefulWidget的build方法放在State中
///   1.build出来的Widget是需要依赖State中的变量(状态/数据)
///   2.在Flutter的运行过程中:
///     Widget是不断的销毁和创建的
///     当我们自己的状态发生改变时, 并不希望重新状态一个新的State

/// State是加_: 这样状态这个类只是给StatefulWidget内部使用
class _HomeViewState extends State<HomeView> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    /// 居中Widget
    return Center(
      /// Column小部件:当有垂直方向布局时,就使用它;
      child: Column(
        /// 居中
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          _getButtons(),
          Text(
            "当前计数:$_counter",
            style: TextStyle(fontSize: 25),
          ),
          Text("传递的信息:${widget.message}")
        ],
      ),
    );
  }

  Widget _getButtons() {
    /// Row小部件:当时水平方向布局时,就使用它
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        /// RaiseButton小部件:可以创建一个按钮,并且其中有一个onPressed属性是传入一个回调函数,当点击按钮时回调
        RaisedButton(
          child: Text(
            "+",
            style: TextStyle(fontSize: 20, color: Colors.white),
          ),
          color: Colors.pink,
          onPressed: () {
            /// 手动调用setState方法,会根据最新的状态(数据)来重新调用build方法,构建对应的Widgets
            setState(() {
              _counter++;
            });
          },
        ),
        RaisedButton(
            child: Text(
              "-",
              style: TextStyle(fontSize: 20, color: Colors.white),
            ),
            color: Colors.purple,
            onPressed: () {
              setState(() {
                _counter--;
              });
            }),
      ],
    );
  }
}

生命周期

StatelessWidget生命周期
import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeWidget(),
    );
  }
}

class HomeWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return HomeView("1111");
  }
}

// StatelessWidget的生命周期
class HomeView extends StatelessWidget {
  HomeView() {
    print("1---构造函数被调用");
  }

  @override
  Widget build(BuildContext context) {
    print("2---调用build方法");
    return Text("111");
  }
}
flutter: 1---构造函数被调用
flutter: 2---调用build方法
StatefulWidget生命周期
import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeWidget(),
    );
  }
}

class HomeWidget extends StatefulWidget {
  @override
  _HomeWidgetState createState() => _HomeWidgetState();
}

class _HomeWidgetState extends State<HomeWidget> {
  @override
  Widget build(BuildContext context) {
    /// Scaffold是脚手架,区分大小写
    return Scaffold(
      /// Scaffold提示区分大小写
      appBar: AppBar(
        title: Text("StatefulWidget的生命周期"),
      ),
      body: HomeView(),
      floatingActionButton: RaisedButton(
        child: Icon(Icons.add),
        /// 点击这里会让HomeView重新构建,这时就会触发HomeViewState的didUpdateWidget方法
        onPressed: () {
          setState(() {
            print("rebuid Widget");
          });
        },
      ),
    );
  }
}

// StatefulWidget的生命周期
class HomeView extends StatefulWidget {
  HomeView() {
    print("1---调用HomeView的constructor方法");
  }

  @override
  _HomeViewState createState() {
    print("2---调用HomeView的createState方法");
    return _HomeViewState();
  }
}

class _HomeViewState extends State<HomeView> {
  int _counter = 0;

  _HomeViewState() {
    print("3---调用_HomeViewState的constructor方法");
  }

  /// 执行initState,我们通常会在这个方法中执行一些数据初始化的操作,或者也可能会发送网络请求
  /// 这个方法是重写父类的方法,必须调用super,因为父类中会进行一些其他操作;
  /// initState上有一个注解(annotation):@mustCallSuper
  @override
  void initState() {
    // 调用: 这里是必须调用super
    final TextStyle style = TextStyle();

    super.initState();
    print("4---调用_HomeViewState的initState方法");
  }

  /// 执行didChangeDependencies方法,这个方法在两种情况下会调用
  ///   情况一:调用initState会调用;
  ///   情况二:从其他对象中依赖一些数据发生改变时,比如前面我们提到的InheritedWidget(这个后面会讲到);
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("5---调用_HomeViewState的didChangeDependencies方法");
  }

  /// 执行build方法,来看一下我们当前的Widget需要渲染哪些Widget
  @override
  Widget build(BuildContext context) {
    print("6---调用_HomeViewState的build方法");
    return Column(
      children: <Widget>[
        RaisedButton(
          child: Icon(Icons.add),
          onPressed: () {
            setState(() {
              _counter++;
            });
          },
        ),
        Text("数字:$_counter")
      ],
    );
  }

  /// 当前的Widget不再使用时,会调用dispose进行销毁
  @override
  void dispose() {
    print("---调用_HomeViewState的dispose方法");
    super.dispose();
  }

  /// 执行didUpdateWidget方法是在当父Widget触发重建(rebuild)时,系统会重新构建Widget时会调用didUpdateWidget方法
  @override
  void didUpdateWidget(HomeView oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("---didUpdateWidget");
  }
}
flutter: 1---调用HomeView的constructor方法
flutter: 2---调用HomeView的createState方法
flutter: 3---调用_HomeViewState的constructor方法
flutter: 4---调用_HomeViewState的initState方法
flutter: 5---调用_HomeViewState的didChangeDependencies方法
flutter: 6---调用_HomeViewState的build方法

// 这里是Android Studio里才会打印,VSCode里就不会,具体原因不详
flutter: 1---调用HomeView的constructor方法
flutter: ---didUpdateWidget
flutter: 6---调用_HomeViewState的build方法
flutter: rebuid Widget
flutter: 1---调用HomeView的constructor方法
flutter: ---didUpdateWidget
flutter: 5---调用_HomeViewState的build方法

命令式编程 和 声明式编程

上一篇 下一篇

猜你喜欢

热点阅读