likes
comments
collection
share

初探Flutter2.x => 十分钟实现一个Flutter列表

作者站长头像
站长
· 阅读数 5

Flutter环境配置

  • Flutter的sdk安装在哪个地方合适?
    • Flutter的SDK中包含了很多命令行工具, 我们需要配置环境变量, 建议安装到平时放命令行工具的地方.
    • 如果你的Mac只有一个用户, 安装在家目录~/flutter下挺合适, 不用考虑权限
    • 放在opt时要考虑到权限
  • 环境配置
    • 来到你对应的Shell配置文件进行配置
    • 如果你使用默认的bash, 那么配置 ~/.bash_profile
    • 如果你是用zsh(Mac新系统默认是zsh), 那么配置~/.zshrc
# Flutter 镜像配置, 解决墙的问题
$ export PUB_HOSTED_URL=https://pub.flutter-io.cn
$ export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
  • 配置FLutter环境变量
#Flutter 配置
$ export FLUTTER=~/flutter
$ export PATH=$FLUTTER/bin:$PATH
  • 配置完成后, 重新打开终端或者输入命令载入配置
# bash则使用.bash_profile
$ source ~/.zshrc
  • 用doctor检测命令, 检测你的Flutter环境是否配置成功flutter doctor

  • 创建方式的几种方式

    • 命令行工具flutter create
    • AS创建
    • Flutter App
    • Flutter Module 混合开发
    • Flutter plugin 插件(带有安卓/iOS原生代码, 不一样)
    • Flutter Package 三方库(只有Dart代码)
    • Empty Project 空工程, 测试用
  • 创建项目名称不能用驼峰命名法, 下划线全用小写字母

Linux环境变量的配置问题

  • 要让shell找到你的工具.
  • Mac上有哪些shell?
    • 早期的bash 配置文件 ~/.bash_profile
    • 更加强大的zsh 配置文件 ~/.zshrc
  • which flutter查看flutter的安装位置
  • flutter doctor, 此时是shell在调用
  • 保证用英文输入法!
  • 很多文本编辑器自带了格式
  • $表示展开变量
  • 配置在.bash_profile有什么区别?
  • 换成zsh原来的配置文件还在bash_profile, 这是怎么办?
  • 建议用哪个shell, 写哪个shell的对应文件.

Flutter2.x实操

  • Flutter的代码为啥能在安卓/iOS上同时运行?
    • iOS/安卓 渲染引擎
    • RN: 原生UI的基础上, 进行包装, 对于原生的依赖非常大
    • 不再用原生的UI了, 把渲染引擎安装在了手机里面, 负责解析Dart代码, 渲染界面, 弊端是安装包大, 优点是效率高, 不依赖原生UI; 高度统一
    • Debug时有热重载, Release中为了适配苹果审核, 没有热更新

初探Flutter2.x => 十分钟实现一个Flutter列表

初探Flutter2.x => 十分钟实现一个Flutter列表

  • 目录放在哪里?

    • 重新选择目录时记得在尾部加上项目名
  • Dart代码在lib目录下面

  • AndroidStudio有一个小小的bug

    • 如果正在执行工程的时候cmd + Q强退锁死, 会锁住当前的运行环境, 再次打开运行时就会出问题, 缓存机制
    • 这时需要删除缓存文件flutte/bin/cache, 删除lockfile
  • 入口是main.dart的main函数

  • material库, 类似于iOS的UIKit.

  • 万物皆是Widget, 类似于iOS的UIView

  • flutter之所以效率高, 核心渲染机制里面的增量渲染

  • iOS里想要某个UI控件发生变化, 给变量里的某个属性赋值; flutter里面相当于改变的不是控件里的成员属性, 谁变了去渲染谁, 直接改变的是控件本身, 上层的渲染树不变, 就没有了iOS的图层!, 后面如果不会改变, 就会适时提示用const.

  • 逆向就不能从UI入手, 因为脱离了原生.

  • 无状态stateless的Widget不可变, 有状态stateful的Widget内部小部件可以变化状态.

  • 本质上都是无状态, stateless的变种封装

  • 类名是驼峰, 工程文件名是小写下划线

  • 自定义的小部件要能被渲染显示出来, 必须重写build方法

  • AS快捷键

    • Alt + Enter, 把提示写出来
    • cmd -折起
    • cmd +打开
  • 热重载, Flutter的一个优点是即使项目很大了, 改了一个东西, 由于增量渲染只改增量文件, 点击热重载按钮就能立刻渲染

  • 渲染树发生了变化, 热更新就没有了意义, 需要重新启动

  • 有状态的StatefulWidget, 状态不能清零, 想要状态清零需要重新启动

import 'package:flutter/material.dart'

void main() {
    runApp(
        const Center(
            child: Text(
                'hello flutter',
                textDirection: TextDirection,ltr
            ),
        )
    );
}

void main() => runApp(MyWidget());

class MyWidget extends StatelessWidget {
    @overrid
    Widget build(BuildContext context) {
        return const Center(
            child: Text(
                'helloFlutter',
                textDirection: TextDirection.rtl,
            )
        )
    }
}

Flutter中的文字样式

  • Text()是调用了一个构造函数
  • OC中是 UIView *view = UIView的构造方法
  • Flutter中不是把成员属性暴露给你, final修饰的最终变量只能被赋值一次
  • 只改变某一个Widget的值
  • iOS中界面和对象是分开的, Flutter中整个界面是一个树状的
  • 创建一个模型对象, 不渲染, 通过模型对象创建新的Widget界面对象, 替换掉后渲染
  • 被干掉的控件没有复用的概念, 没有iOS中指针变量指向的用法,
  • Colors是一个独立的类, 点上静态属性, Colors.red, 文档中可以看到设计
  • MaterialApp, Scaffold
  • 不会变, 去除警告, 添加const
  • 垂直居中想对于父Widget
void main() => runApp(MyWidget());

class App extends StatelessWidget{
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            home: Scaffold(
                appBar: AppBar(
                    title: const Text('Flutter标题'),
                ),
                body: MyWidget(),
            ),
        );
    }
}

class MyWidget extends StatelessWidget {
    @overrid
    Widget build(BuildContext context) {
        return const Center(
            child: Text(
                'helloFlutter1122333',
                textDirection: TextDirection.rtl,
                sytle: TextStyle(
                    fontSize: 40.0, 
                    fontWeight: FontWeight.bold,
                    color: Color.fromARGB(0.9, 0, 0, 255),// 命名构造函数
                ),
            )
        )
    }
}

初探Flutter中的TableView

  • 创建文件夹, 文件夹名称和文件都小写
  • 类名开头都是大写
  • ?空安全
  • 写代码时直接写类名, 敲回车直接就会帮忙引入头文件
  • Opt + Enter直接帮忙创建类
  • Widget的排列只有三种
    • 横着
    • 竖着
    • 叠着
  • 怎么看出是异步加载的? 首先显示的是文字, 图片下载好展示
  • 找到跟iOS的共性
  • flutter官方文档, dart的包Dart packages

初探Flutter2.x => 十分钟实现一个Flutter列表

import 'package:flutter/material.dart'
import 'model/car.dart'

void main() => runApp(App());

class App extends StatelessWidget{
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            deubgShowCheckedModeBanner: false, // 除去Debug标签
            home: Home(),
        );
    }
}

class Home extends StatelessWidget {
    // _的内部是指文件内部
    Widget _itemForRow(BuildContext context, int index) {
        return Container(
            color: Coplors.white,
            margin: const EdgeInsets.all(10),
            child: Column(
                children: <Widget>[
                    Image.network(datas[index].imageURL!),
                    Container(height: 10),
                    Text(
                        datas[index].name!,
                        style: const TextStyle(
                            fontWeight: FontWeight.w800,
                            fontSize: 18.0
                        ),
                    ),
                ],
            ),
        );
    }
    
    @override
    Widget build(BuildContext context) {
        return Scafflod(
            backgroudColor: Colors.grey[100],
            appBar: AppBar(
                title: const Text('标题'),
            ),
            body: ListView.builder(
                itemBuilder: _itemForRow,
                itemCount: datas.length
            ),
        );
    }
    
}

final List<Car> datas = [
    const Car(
        name: '保时捷'
        imageURL: 'https://img0.baidu.com/it/u=1875746338,171164291&fm=253&fmt=auto&app=120&f=JPEG?w=846&h=477',
    ),
    const Car(
        name: '奔驰'
        imageURL: 'https://img0.baidu.com/it/u=2269620487,3600909808&fm=253&fmt=auto&app=120&f=JPEG?w=667&h=500',
    ),
    const Car(
        name: '宝马'
        imageURL: 'https://img1.baidu.com/it/u=1628168174,64924477&fm=253&fmt=auto&app=120&f=JPEG?w=890&h=500',
    ),
];

class Car{
    const Car(this.name, this.imageURL);

    final String name;
    final String imageURL;
    
}

最终效果截图

初探Flutter2.x => 十分钟实现一个Flutter列表

Tips

  • Flutter的特点

    • 不依赖原生UI, 拥有独立的渲染引擎
    • 界面更新逻辑和原生不一样(增量渲染), 重新创建一个新的Widget
  • 为什么Flutter中大量的final(只能赋值一次, 最终变量)修饰的属性, const修饰的构造方法(常量对象)

    • 因为Flutter的渲染逻辑是增量渲染, Widget结构是树状结构.
    • 想改变屏幕内容就直接改变Widget对象(干掉原来的Widget, 重新创建Widget, 实时快速的创建).
    • 常量对象的创建效率更高!
  • Scafflod小部件

    • 带有导航栏(appBar)的小部件
    • body属性

抽取ListView

listview_demo.dart

import 'package:flutter/material.dart'
import 'model/car.dart'


class ListViewDemo extends StatelessWidget {
    // _的内部是指文件内部
    Widget _itemForRow(BuildContext context, int index) {
        return Container(
            color: Coplors.white,
            margin: const EdgeInsets.all(10),
            child: Column(
                children: <Widget>[
                    Image.network(datas[index].imageURL!),
                    Container(height: 10),
                    Text(
                        datas[index].name!,
                        style: const TextStyle(
                            fontWeight: FontWeight.w800,
                            fontSize: 18.0
                        ),
                    ),
                ],
            ),
        );
    }
    
    @override
    Widget build(BuildContext context) {
        return Scafflod(
            backgroudColor: Colors.grey[100],
            appBar: AppBar(
                title: const Text('标题'),
            ),
            body: ListView.builder(
                itemBuilder: _itemForRow,
                itemCount: datas.length
            ),
        );
    }
    
}