文章目录
- 前言
- 相关链接
- 初始化项目
- 设置键盘映射
- 建议使用AnLink链接物理机。
- 项目配置
- 日志打印
- 官方案例
- 添加依赖
- 主函数更换
- 添加最简单的按钮
- Flutter 项目结构
- Flutter项目入口
- Flutter的MyApp函数
- 更新视图
- 直接修改
- 浅拷贝父节点数据
- 思考
- 修改布局
- 子节点重构
- 子节点布局重构
- 多次扩展布局
- 设置颜色主题
前言
为了得到的得到Uniapp的上位替代,最近打算使用Flutter开发。一般开发需要3个UI框架,icons库+UI框架+统计图
相关链接
【Flutter – 基础】快速入门 Flutter
Flutter 中文文档
编写第一个 Flutter 应用
初始化项目
注意,后续的代码主要就是抄官方的案例来的
编写第一个 Flutter 应用
设置键盘映射
我习惯用vscode 的快捷键了,这里设置一下。
建议使用AnLink链接物理机。
项目配置
# 降低代码检验的标准,让我们更简单的使用dart
linter:
rules:
prefer_const_constructors: false
prefer_final_fields: false
use_key_in_widget_constructors: false
prefer_const_literals_to_create_immutables: false
prefer_const_constructors_in_immutables: false
avoid_print: false
日志打印
日志打印使用[print]函数即可
print('hello flutter');
官方案例
添加依赖
在[pubspec.yaml]中添加
name: namer_app
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.1+1
environment:
sdk: '>=2.19.4 <4.0.0'
# 这个就是Flutter对应的第三方库了
dependencies:
flutter:
sdk: flutter
english_words: ^4.0.0
provider: ^6.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
主函数更换
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => MyAppState(),
child: MaterialApp(
title: 'Namer App',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
),
home: MyHomePage(),
),
);
}
}
class MyAppState extends ChangeNotifier {
var current = WordPair.random();
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var appState = context.watch<MyAppState>();
return Scaffold(
body: Column(
children: [
Text('A random idea:'),
Text(appState.current.asLowerCase),
],
),
);
}
}
确保没有报错之后测试运行
添加最简单的按钮
return Scaffold(
body: Column(
children: [
Text('A random idea str:'),
Text(appState.current.asLowerCase),
//添加新的按钮
ElevatedButton(
onPressed: () {
print('button click');
},
child: Text('Next'))
],
),
);
Flutter 项目结构
Flutter项目入口
Flutter的MyApp函数
MyApp就是项目的布局入口了,类似于Wpf/windows里面的窗口。标注这整个外部的容器的形状
详细的请看官方教程
目前看下来是单向数据流的向下数据流。在React和Vue中,都是自顶向下的数据流。什么是数据流呢?在我看来,就是数据改变自动触发,自动传递的就是数据流。
为什么一般都是向下数据流呢,因为我们认为,父节点的数据是先生成,范围广,更准确的。就好像是从上流的水往下流一样,可以更能保证整个项目的稳定行。如果是向上数据流的话,那随意添加一个子节点都可能导致父节点发送改动。如果是双向数据流的话,会导致数据流动的方向不明确,难以维护。
那子节点又是怎么通知父节点的呢?一般都是通过函数回调的形式,就是手动通知父节点。相当于需要更加繁琐,明确的操作来保证父节点的数据稳定。
更新视图
更新视图需要用到notifyListeners,这个是用于通知视图的方法。在React和WPF中都是手动通知的,在Vue中是自动通知的。手动通知的好处就是可以操控。
注意:Dark有自己的命名规范,class大驼峰,类名和方法名都是小驼峰。
将[MyAppState]进行修改
//可通知视图修改的类
class MyAppState extends ChangeNotifier {
//这个就相当于成员变量
var current = WordPair.random();
//手动声明回调函数,理论上来说,最好通过函数显性修改父节点属性
void getNext(){
current = WordPair.random();
// 手动通知刷新视图元素
notifyListeners();
}
//手动通知
void notify(){
notifyListeners();
}
}
直接修改
return Scaffold(
body: Column(
children: [
Text('A random idea str:'),
Text(appState.current.asLowerCase),
//添加新的按钮
ElevatedButton(
onPressed: () {
print('button click');
//直接修改父节点属性
appState.current = WordPair.random();
//手动更新通知
appState.notify();
//上面两步等于下面一步,但是还是建议使用函数有限制的回调
//appState.getNext();
},
child: Text('Next'))
],
),
);
浅拷贝父节点数据
为了防止父节点的数据遭到随意的修改,我们这里使用浅拷贝来复刻父节点的数据
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
//拿到父节点,由于父节点是单例,所以不需要别名
var appState = context.watch<MyAppState>();
//为了解决复杂的代码逻辑,在函数开头拿到数据,而不是直接对父节点的数据进行修改
//这里是浅拷贝,不是深拷贝
var pair = appState.current;
return Scaffold(
body: Column(
children: [
Text('A random idea str:'),
// Text(appState.current.asLowerCase),
Text(pair.asLowerCase),
//添加新的按钮
ElevatedButton(
onPressed: () {
print('button click');
//直接修改父节点属性
// pair = WordPair.random();
//手动更新通知
// appState.notify();
//上面是浅拷贝的修改,无法反馈到父节点
appState.getNext();
},
child: Text('Next'))
],
),
);
}
}
思考
所以我们的节点应该都是这么挂的
- MyApp + MyAppState
- MyHomePage + appState=MyAppState,这里的appState都是向上一级的父节点属性
所以我现在的问题就是如果一个父节点挂载多个子节点,会如何。现在还不了解
修改布局
子节点重构
右键Text节点,Refactor->Extarct Flutter Widget
子节点布局重构
多次扩展布局
在Padding布局外侧添加Card布局
设置颜色主题
@override
Widget build(BuildContext context) {
final theme = Theme.of(context); // ← Add this.
return Card(
color: theme.colorScheme.primary, // ← And also this.
child: Padding(
padding: const EdgeInsets.all(20),
child: Text(pair.asLowerCase),
),
);
}