Flutter学习2:构建一个简单的ListView

![学习ing](https://upload-images.jianshu.io/upload_images/6266734-bacca04c00b75e7d.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


## 1. 热重载
### 1.1 什么是热重载

* Flutter**热重载**:在我们调试布局的时候,更改代码,模拟器上可以立即看到代码改动的效果;而不是iOS和Android单独开发需要重新编译,启动,耗时极长。  
***
* **开发效率**:Flutter的热重载可帮助开发者快速地进行测试、构建UI、添加功能并更快地修复错误。在iOS和Android模拟器或真机上可以实现毫秒级热重载,并且不会丢失状态。这真的很棒,相信我,如果你是一名原生开发者,体验了Flutter开发流后,很可能就不想重新回去做原生了,毕竟很少有人不吐槽原生开发的编译速度。

### 1.2 热重载的使用
热重载快捷键:
>command + \  

或者直接点击热重载按钮,闪电标识:
![热重载按钮](https://upload-images.jianshu.io/upload_images/6266734-ea9764ac637673db.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

如果使用终端直接run,热重载直接输入小写的 **r**,即可;热重启直输入大写的 **R**,即可

![终端热重载指令,输入r,R](https://upload-images.jianshu.io/upload_images/6266734-0040f2b2c76bf229.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


## 2. 常用快捷键的使用

1. Dart语言命名规则:  
**文件名**:小写 + _ (组合使用,不需要驼峰规则)  
**类名** :首字母大写 + 驼峰规则

2. **格式化**:  按照Dart的语法规则将代码格式优化   
   command + option + l

3. **function折叠**:  将{}之间的方法折叠为{...}或展开  
   command -  
   command +
             
4. **代码块的使用**:   
   stl  (无状态stateless widget)   
   stf  (有状态stateful widget)  

5. **import快捷键**:   当使用一个没有import的类时报错,可以使用如下快捷键  
   option + enter两次

6. **切换文件**:  在两个.dart文件之间来回切换  
   command + [   
   command + ]

7. **打开一个文件**:  
   command + shift + o
   
8. 当一个function里面只有一句执行代码的时候,可以用=>简写,如下:  
   >void main() {  
   >runApp(App();  //只有一句执行代码  
   > }  
   
   void main() => runApp(App()); 
   
## 3. 简单ListView的搭建

 Flutter中的ListView类似于iOS中的UITableView,使用之处和iOS的UITableView类似也有区别;
### 3.1 Widget控件
* 在Flutter中几乎所有的对象都是一个Widget。与原生开发中“控件”不同的是,Flutter中的Widget的概念更广泛,它不仅可以表示UI元素,也可以表示一些功能性的组件如:用于手势检测的 GestureDetector widget、用于APP主题数据传递的Theme等等,而原生开发中的控件通常只是指UI元素。在后面的内容中,我们在描述UI元素时可能会用到“控件”、“组件”这样的概念,读者心里需要知道他们就是widget,只是在不同场景的不同表述而已。由于Flutter主要就是用于构建用户界面的,所以,在大多数时候,读者可以认为widget就是一个控件,不必纠结于概念。
 
 Widget主要接口:  
 
 ```dart
 @immutable
abstract class Widget extends DiagnosticableTree {
  const Widget({ this.key });
  final Key key;

  @protected
  Element createElement();

  @override
  String toStringShort() {
    return key == null ? '$runtimeType' : '$runtimeType-$key';
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
  }

  static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
  }
}
 ```
* Widget类继承自DiagnosticableTree,DiagnosticableTree即“诊断树”,主要作用是提供调试信息。
* Key: 这个key属性类似于React/Vue中的key,主要的作用是决定是否在下一次build时复用旧的
* widget,决定的条件在canUpdate()方法中。
* createElement():正如前文所述“一个Widget可以对应多个Element”;Flutter Framework在构建UI树时,会先调用此方法生成对应节点的Element对象。此方法是Flutter Framework隐式调用的,在我们开发过程中基本不会调用到。
* debugFillProperties(...) 复写父类的方法,主要是设置诊断树的一些特性。
* canUpdate(...)是一个静态方法,它主要用于在Widget树重新build时复用旧的widget,其实具体来说,应该是:是否用新的Widget对象去更新旧UI树上所对应的Element对象的配置;通过其源码我们可以看到,只要newWidget与oldWidget的runtimeType和key同时相等时就会用newWidget去更新Element对象的配置,否则就会创建新的Element。 

以上摘自Flutter官方文档Widget概述:[Flutter中文网Widget概述](https://book.flutterchina.club/chapter3/flutter_widget_intro.html)

简单来说Widget就相当于iOS中的UIView

### 3.2 主要代码

代码主要分为3部分:  
1. main.dat:主界面,导航栏等;  
2. listview_demo.dart 列表listview对象控件;  
3. car.dart 单个widget模型(name,imageUrl);

* main.dart中的代码:

```dart
//material.dart相当于iOS中的UIKit
import 'package:flutter/material.dart';
import 'package:flutter_001/model/listview_demo.dart';

//Widget 控件 相当于UIView
//Stateful 有状态的控件  Stateless 无状态的控件

//void main (){
//  
//  runApp(
//     App(),
//  );
//}

//当一个function里面只有一句执行代码的时候,可以用=>简写
//如下:

void main() => runApp(App());
//runApp相当于iOS中的UIApplication

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: true,
      home: Home(),//首页
      theme: ThemeData(
        primaryColor: Colors.yellow,//导航栏颜色
      ),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      //appBar 导航栏
      appBar: AppBar(title: Text(
        "ListView",
        style: TextStyle(
        color: Colors.deepOrange[300],
     fontSize: 22,
        ),
      ),
      ),
      body: ListViewDemo(),  //ListView控件
    );

  }
}

```  
* 列表listview_demo的代码:

```dart
import 'package:flutter/material.dart';

import 'car.dart'; //option +enter两次

class ListViewDemo extends StatelessWidget {
  Widget _cellForRow (BuildContext context, int index){ 
  //自定义返回cell的函数
  //context:上下文
  //index:第几个widget(第几个cell)

    return Container(
      margin: EdgeInsets.all(10),
      color: Colors.white,
      child: Column(
        children: <Widget>[
          Image.network(datas[index].imageUrl),
          SizedBox(height:20),
          Text(datas[index].name,style:
          TextStyle(color:Colors.blue,
            fontSize:22,
            fontWeight: FontWeight.w800,
            fontStyle: FontStyle.values[1],
          )),
          SizedBox(height: 20),
        ],
      ),
    );
  }

  //Column 上下布局
  //Row    左右布局
  //Stack  层级布局

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        itemCount: datas.length,
        itemBuilder: _cellForRow);
  }
  // ListView.builder创建listView,需要传入的参数有
  // itemCount: 简单理解UITableView中的cell的个数;
  // itemBuilder: 简单理解UITableView中的cellforRowsAtIndex;
  // Dart中带_的方法为私有方法,外部不能访问,例如_cellForRow;
}
```
* 模型car.dart文件中的代码:

```dart
class Car {

  const Car ({ //构造函数
    this.name,
    this.imageUrl,

  });
  final String name;
  final String imageUrl;
}

//数据源数组:
final List<Car> datas = [
  Car(
    name: '保时捷918 Spyder',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '兰博基尼Aventador',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '法拉利Enzo',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: 'Zenvo ST1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '迈凯伦F1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '萨林S7',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '科尼赛克CCR',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-01ced8f6f95219ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '布加迪Chiron',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7fc8359eb61adac0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '轩尼诗Venom GT',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-d332bf510d61bbc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '西贝尔Tuatara',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-3dd9a70b25ae6bc9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  )

];

```

![运行效果](https://upload-images.jianshu.io/upload_images/6266734-157ef5d01bba773c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
 

Flutter学习2:构建一个简单的ListViewFlutter学习2:构建一个简单的ListView wyyrls 发布了3 篇原创文章 · 获赞 0 · 访问量 42 私信 关注
上一篇:20191310Lee_yellow缓冲区溢出实验


下一篇:CSS_2——伪元素选择器