百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Flutter完整开发实战详解(一、Dart语言和Flutter基础)

toyiye 2024-07-06 00:33 26 浏览 0 评论

前言

在如今的 Fultter 大潮下,本系列是让你看完会安心的文章。本系列将完整讲述:如何快速从0开发一个完整的 Flutter APP。同时也会提供一些Flutter的开发细节技巧,并针对开发过程中可能遇到的问题进行填坑。

系列文章分为三篇,第一部分是基础篇(针对Dart语言和Flutter基础),第二部分是App快速开发实战篇,第三部分是细节填坑篇。

笔者相继开发过 Flutter、React Native 、Weex 等主流跨平台框架项目,其中 Flutter 的跨平台兼容性无疑最好。前期开发调试完全在 Android 端进行的情况下,第一次在 IOS 平台运行居然没有任何错误,并且还没出现UI兼容问题,相信对于经历过跨平台开发的猿们而言,这是多么的不可思议画面。并且 Fluuter 的 HotLoad 相比较其他两个平台,也是丝滑的让人无法相信。吹爆了!

这些特点其实这得益于Flutter Engine 和 Skia ,好了,感慨那么多,让我们进入正题吧。

一、基础篇

本篇主要涉及:环境搭建、Dart语言、Flutter的基础。

1、环境搭建

Flutter 的环境搭建十分省心,特别对应 Android 开发者而言,只是在 Android Stuido

上安装插件,并下载flutter Sdk到本地,配置在环境变量即可。其实中文网的搭建Futter开发环境 已经很贴心详细,从平台指引开始安装基本都不会遇到问题。

这里主要是需要注意,因为某些不可抗力的原因,国内的用户需要配置 Flutter 的代理,并且国内用户在搜索 Flutter 第三方包时,也是在 https://pub.flutter-io.cn 内查找,下方是需要配置到环境变量的地址。(ps Android Studio下运行 IOS 也是蛮有意思的(???))

///win直接配置到环境编辑即可,mac配置到bash_profile
export PUB_HOSTED_URL=https://pub.flutter-io.cn //国内用户需要设置
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn //国内用户需要设置

2、Dart语言下的Flutter

在跨平台开领域被 JS 一统天下的今天,Dart 语言的出现无疑是一股清流。作为后来者,Dart语言有着不少Java、kotlin 和 JS 的影子,所以对于 Android 原生开发者、前端开发者而言无疑是非常友好的。

官方也提供了包括IOS开发者,React Native 等开发者迁移到 Flutter 上的文档,所以请不要担心,Dart语言不会是你掌握 Flutter 的门槛。甚至作为开发者,就算你不懂 Dart 也可以看着代码摸索。

Come on,下面主要通过对比,简单讲述下 Dart 的一些特性,主要涉及的是 Flutter 下使用。

  • 基本类型

var 可以定义变量,如 var tag = "666" ,这和 JS 、 Kotlin 等语言类似,同时 Dart 属于动态类型语言,支持闭包。

Dart 中 number 类型分为 int 和 double ,其中 java 中的 long 对应的也是 Dart 中的 int 类型。Dart 中没有 float 类型。

Dart 下只有 bool 型可以用于 if 等判断,不同于 JS 这种使用方式是不合法的 var g = "null"; if(g){} 。

DART中,switch 支持 String 类型。

  • 变量

Dart 不需要给变量设置 setter getter 方法, 这和 kotlin 等类似。Dart 中所有的基础类型、类等都继承 Object ,默认值是 NULL, 自带 getter 和 setter ,而如果是 final 或者 const 的话,那么它只有一个 getter 方法。

Dart 中 final 和 const 表示常量,比如 final name = 'GSY'; const value= 1000000; 同时 static const 组合代表了静态常量。其中 const 的值在编译期确定,final 的值要到编译时才确定。(ps Flutter 在 Release 下是 AOT 模式。)

Dart 下的数值,在作为字符串使用时,是需要显式指定的。比如:int i = 0; print("aaaa" + i); 这样并不支持,需要 print("aaaa" + i.toString()); 这样使用。这和 Java 与 JS 存在差异。所以在使用动态类型时,需要注意不要把 number 类型当做 String 使用。

DART 中数组等于列表,所以 var list = []; 和 List list = new List() 可以简单看做一样。

  • 方法

Dart 下 ?? 、??= 属于操作符,如: AA ?? "999" 表示如果 AA 为空,返回999;AA ??= "999" 表示如果 AA 为空,给 AA 设置成 999。

Dart 方法可以设置 参数默认值指定名称 。比如: getDetail(Sting userName, reposName, {branch = "master"}){} 方法,这里 branch 不设置的话,默认是 “master” 。参数类型 可以指定或者不指定。调用效果: getRepositoryDetailDao(“aaa", "bbbb", branch: "dev");

Dart 不像 Java ,没有关键词 public 、private 等修饰符,_下横向直接代表 private ,但是有 @protected 注解。

Dart 中多构造函数,可以通过如下代码实现的。默认构造方法只能有一个,而通过Model.empty() 方法可以创建一个空参数的类,其实方法名称随你喜欢。而变量初始化值时,只需要通过 this.name 在构造方法中指定即可:

class ModelA {
 String name;
 String tag;
 
 //默认构造方法,赋值给name和tag
 ModelA(this.name, this.tag);
 //返回一个空的ModelA
 ModelA.empty();
 
 //返回一个设置了name的ModelA
 ModelA.forName(this.name);
}
  • Flutter

Flutter 中支持 async/await 。这一点和 ES7 很像,如下代码所示,只是定义的位置不同。同时异步操作也和 ES6 中的Promise 很像,只是 Flutter 中返回的是 Future 对象,通过 then 可以执行下一步。如果返回的还是 Future 便可以 then().then.() 的流式操作了 。

 ///模拟等待两秒,返回OK
 request() async {
 await Future.delayed(Duration(seconds: 1));
 return "ok!";
 }
 ///得到"ok!"后,将"ok!"修改为"ok from request"
 doSomeThing() async {
 String data = await request();
 data = "ok from request";
 return data;
 }
 ///打印结果
 renderSome() {
 doSomeThing().then((value) {
 print(value);
 ///输出ok from request
 });
 }

Flutter 中 setState 很有 React Native 的既视感,Flutter 中也是通过 state 跨帧实现管理数据状态的,这个后面会详细讲到。

Flutter 中一切皆 Widget 呈现,通过 build方法返回 Widget,这也是和 React Native 中,通过 render 函数返回需要渲染的 component 一样的模式。

3、Flutter Widget

在 Flutter 中,一切的显示都是 Widget 。Widget 是一切的基础,作为响应式的渲染,属于 MVVM 的实现机制。我们可以通过修改数据,再用setState 设置数据,Flutter 会自动通过绑定的数据更新 Widget 。所以你需要做的就是实现 Widget 界面,并且和数据绑定起来。

Widget 分为 有状态无状态 两种,在 Flutter 中每个页面都是一帧。无状态就是保持在那一帧。而有状态的 Widget 当数据更新时,其实是绘制了新的 Widget,只是 State 实现了跨帧的数据同步保存。

这里有个小 Tip ,当代码框里输入 stl 的时候,可以自动弹出创建无状态控件的模板选项,而输入 stf 的时,就会弹出创建有状态 Widget 的模板选项。

代码格式化的时候,括号内外的逗号都会影响格式化时换行的位置。

如果觉得默认换行的线太短,可以在设置-Editor-Code Style-Dart-Wrapping and Braces-Hard wrap at 设置你接受的数值。

3.1、无状态StatelessWidget

直接进入主题,下方代码是无状态 Widget 的简单实现。

继承 StatelessWidget,通过 build 方法返回一个布局好的控件。可能现在你还对 Flutter 的内置控件不熟悉,but Don't worry , take is easy ,后面我们就会详细介绍。这里你只需要知道,一个无状态的 Widget 就是这么简单。?

Widget 和 Widget 之间通过 child: 进行嵌套。其中有的 Widget 只能有一个 child,比如下方的 Container ;有的 Widget 可以多个 child ,也就是children:,比如` Colum 布局。下方代码便是 Container Widget 嵌套了 Text Widget。

import 'package:flutter/material.dart';
class DEMOWidget extends StatelessWidget {
 final String text;
 //数据可以通过构造方法传递进来
 DEMOWidget(this.text);
 @override
 Widget build(BuildContext context) {
 //这里返回你需要的控件
 //这里末尾有没有的逗号,对于格式化代码而已是不一样的。
 return Container(
 //白色背景
 color: Colors.white,
 //Dart语法中,?? 表示如果text为空,就返回尾号后的内容。
 child: Text(text ?? "这就是无状态DMEO"),
 );
 }
}

3.2、有状态StatefulWidget

继续直插主题,如下代码,是有状态的widget的简单实现。

你需要创建管理的是主要是 State , 通过 State 的 build 方法去构建控件。在 State 中,你可以动态改变数据,这类似 MVVM 实现,在 setState 之后,改变的数据会触发 Widget 重新构建刷新。而下方代码中,是通过延两秒之后,让文本显示为 "这就变了数值"

如下代码还可以看出,State 中主要的声明周期有 :

  • initState :初始化,理论上只有初始化一次,第二篇中会说特殊情况下。
  • didChangeDependencies:在 initState 之后调用,此时可以获取其他 State 。
  • dispose :销毁,只会调用一次。

看到没,Flutter 其实就是这么简单!你的关注点只要在:创建你的 StatelessWidget 或者 StatefulWidget 而已。你需要的就是在 build 中堆积你的布局,然后把数据添加到 Widget 中,最后通过 setState 改变数据,从而实现画面变化。

import 'dart:async';
import 'package:flutter/material.dart';
class DemoStateWidget extends StatefulWidget {
 final String text;
 ////通过构造方法传值
 DemoStateWidget(this.text);
 ///主要是负责创建state
 @override
 _DemoStateWidgetState createState() => _DemoStateWidgetState(text);
}
class _DemoStateWidgetState extends State<DemoStateWidget> {
 String text;
 _DemoStateWidgetState(this.text);
 
 @override
 void initState() {
 ///初始化,这个函数在生命周期中只调用一次
 super.initState();
 ///定时2秒
 new Future.delayed(const Duration(seconds: 1), () {
 setState(() {
 text = "这就变了数值";
 });
 });
 }
 @override
 void dispose() {
 ///销毁
 super.dispose();
 }
 @override
 void didChangeDependencies() {
 ///在initState之后调 Called when a dependency of this [State] object changes.
 super.didChangeDependencies();
 }
 @override
 Widget build(BuildContext context) {
 return Container(
 child: Text(text ?? "这就是有状态DMEO"),
 );
 }
}

4、Flutter 布局

Flutter 中拥有需要将近30种内置的 布局Widget,其中常用有 Container、Padding、Center、Flex、Stack、Row、Colum、ListView 等,下面简单讲解它们的特性和使用。

 new Container(
 ///四周10大小的maring
 margin: EdgeInsets.all(10.0),
 height: 120.0,
 width: 500.0,
 ///透明黑色遮罩
 decoration: new BoxDecoration(
 ///弧度为4.0
 borderRadius: BorderRadius.all(Radius.circular(4.0)),
 ///设置了decoration的color,就不能设置Container的color。
 color: Colors.black,
 ///边框
 border: new Border.all(color: Color(GSYColors.subTextColor), width: 0.3)),
 child:new Text("666666"));
  • Colum、Row 绝对是必备布局, 横竖布局也是日常中最常见的场景。如下方所示,它们常用的有这些属性配置:主轴方向是 start 或 center 等;副轴方向方向是 start 或 center 等;mainAxisSize 是充满最大尺寸,或者只根据子 Widget 显示最小尺寸。
//主轴方向,Colum的竖向、Row我的横向
mainAxisAlignment: MainAxisAlignment.start, 
//默认是最大充满、还是根据child显示最小大小
mainAxisSize: MainAxisSize.max,
//副轴方向,Colum的横向、Row我的竖向
crossAxisAlignment :CrossAxisAlignment.center,
  • Expanded 在 Colum 和 Row 中代表着平均充满,当有两个存在的时候默认均分充满。同时页可以设置 flex 属性决定比例。
 new Column(
 ///主轴居中,即是竖直向居中
 mainAxisAlignment: MainAxisAlignment.center,
 ///大小按照最小显示
 mainAxisSize : MainAxisSize.min,
 ///横向也居中
 crossAxisAlignment : CrossAxisAlignment.center,
 children: <Widget>[
 ///flex默认为1
 new Expanded(child: new Text("1111"), flex: 2,),
 new Expanded(child: new Text("2222")),
 ],
 );

接下来我们来写一个复杂一些的控件。首先我们创建一个私有方法_getBottomItem,返回一个 Expanded Widget,因为后面我们需要将这个方法返回的 Widget 在 Row 下平均充满。

如代码中注释,布局内主要是现实一个居中的Icon图标和文本,中间间隔5.0的 padding:

 ///返回一个居中带图标和文本的Item
 _getBottomItem(IconData icon, String text) {
 ///充满 Row 横向的布局
 return new Expanded(
 flex: 1,
 ///居中显示
 child: new Center(
 ///横向布局
 child: new Row(
 ///主轴居中,即是横向居中
 mainAxisAlignment: MainAxisAlignment.center,
 ///大小按照最大充满
 mainAxisSize : MainAxisSize.max,
 ///竖向也居中
 crossAxisAlignment : CrossAxisAlignment.center,
 children: <Widget>[
 ///一个图标,大小16.0,灰色
 new Icon(
 icon,
 size: 16.0,
 color: Colors.grey,
 ),
 ///间隔
 new Padding(padding: new EdgeInsets.only(left:5.0)),
 ///显示文本
 new Text(
 text,
 //设置字体样式:颜色灰色,字体大小14.0
 style: new TextStyle(color: Colors.grey, fontSize: 14.0),
 //超过的省略为...显示
 overflow: TextOverflow.ellipsis,
 //最长一行
 maxLines: 1,
 ),
 ],
 ),
 ),
 );
 }

接着我们把上方的方法,放到新的布局里。如下流程和代码:

  • 首先是 Container包含了Card,用于快速简单的实现圆角和阴影。
  • 然后接下来包含了FlatButton实现了点击,通过Padding实现了边距。
  • 接着通过Column垂直包含了两个子Widget,一个是Container、一个是Row。
  • Row 内使用的就是_getBottomItem方法返回的 Widget ,效果如下图。
 @override
 Widget build(BuildContext context) {
 return new Container(
 ///卡片包装
 child: new Card(
 ///增加点击效果
 child: new FlatButton(
 onPressed: (){print("点击了哦");},
 child: new Padding(
 padding: new EdgeInsets.only(left: 0.0, top: 10.0, right: 10.0, bottom: 10.0),
 child: new Column(
 mainAxisSize: MainAxisSize.min,
 children: <Widget>[
 ///文本描述
 new Container(
 child: new Text(
 "这是一点描述",
 style: TextStyle(
 color: Color(GSYColors.subTextColor),
 fontSize: 14.0,
 ),
 ///最长三行,超过 ... 显示
 maxLines: 3,
 overflow: TextOverflow.ellipsis,
 ),
 margin: new EdgeInsets.only(top: 6.0, bottom: 2.0),
 alignment: Alignment.topLeft),
 new Padding(padding: EdgeInsets.all(10.0)),
 ///三个平均分配的横向图标文字
 new Row(
 crossAxisAlignment: CrossAxisAlignment.start,
 children: <Widget>[
 _getBottomItem(Icons.star, "1000"),
 _getBottomItem(Icons.link, "1000"),
 _getBottomItem(Icons.subject, "1000"),
 ],
 ),
 ],
 ),
 ))),
 );
 }

Flutter 中,你的布局很多时候就是这么一层一层嵌套出来的,当然还有其他更高级的布局方式,这里就先不展开了。

5、Flutter 页面

Flutter 中除了布局的 Widget,还有交互显示的 Widget 和完整页面呈现的Widget。其中常见的有 MaterialApp、Scaffold、Appbar、Text、Image、FlatButton等。下面简单介绍这些 Wdiget,并完成一个页面。

  • 首先我们创建一个StatefulWidget:DemoPage。
  • 然后在 _DemoPageState中,通过build创建了一个Scaffold。
  • Scaffold内包含了一个AppBar和一个ListView。
  • AppBar类似标题了区域,其中设置了 title为 Text Widget。
  • body是ListView,返回了20个之前我们创建过的 DemoItem Widget。
import 'package:flutter/material.dart';
import 'package:gsy_github_app_flutter/test/DemoItem.dart';
class DemoPage extends StatefulWidget {
 @override
 _DemoPageState createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
 @override
 Widget build(BuildContext context) {
 ///一个页面的开始
 ///如果是新页面,会自带返回按键
 return new Scaffold(
 ///背景样式
 backgroundColor: Colors.blue,
 ///标题栏,当然不仅仅是标题栏
 appBar: new AppBar(
 ///这个title是一个Widget
 title: new Text("Title"),
 ),
 ///正式的页面开始
 ///一个ListView,20个Item
 body: new ListView.builder(
 itemBuilder: (context, index) {
 return new DemoItem();
 },
 itemCount: 20,
 ),
 );
 }
}

最后我们创建一个StatelessWidget作为入口文件,实现一个MaterialApp将上方的DemoPage设置为home页面,通过main入口执行页面。

import 'package:flutter/material.dart';
import 'package:gsy_github_app_flutter/test/DemoPage.dart';
void main() {
 runApp(new DemoApp());
}
class DemoApp extends StatelessWidget {
 DemoApp({Key key}) : super(key: key);
 @override
 Widget build(BuildContext context) {
 return new MaterialApp(home: DemoPage());
 }
}

好吧,第一部分终于完了,这里主要讲解都是一些简单基础的东西,适合安利入坑,后续还有两篇主要实战,敬请期待哟!( ̄^ ̄)ゞ

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码