Flutter使用简报

目录

一个Java开发快速入门Dart

Flutter使用简报

一个Android开发快速入门Flutter(一)

一个Android开发快速入门Flutter (二) 

前言

   Flutter个人感觉是移动端开发不错的姿势,相比于其他weex开发也有一定优势。如果你想先初步了解Flutter的话,可以看下这个视频介绍。20多分钟,基本讲述了Flutter的优点和设计思想。对于新入手的人而言,值得花点时间研究下。

    另外本篇博客内容取自于Flutter官网教程,用于记录所获,如果你希望更加获得更加官方的咨询,可参见官网

注意

  1. 上面视频中有个非常炫酷的操作,就是通过改变framework(就是Flutter提供给你的代码),直接修改一个list的表现形式。喂这是正常操作吧,这里的Flutter对于整个ios或者Android来说就是一个三方包,只是经过编译之后变成arm指令。那么你修改三方包里面的源代码,导致表现形式改变不是很正常嘛?忽悠人,差评。
  2. 在Flutter中要建立组件化(widget)的概念,什么都是组件,连整个app都是组件,连padding都是组件,连居中都是组件!
  3. UI从命令式到声明式的转变。怎么理解这句话,这对于Flutter的理解非常重要。

    从上面这张图来说,假设由于某个时间触发,我们需要将当前的view从 左图变到右图。对于从win32就开始的传统的命令式UI来说,首先我们需要获取到ViewB b ,ViewC c1 ViewC c2的实例,然后修改这些实例的状态,比如用android的代码来写可能就差不多是这样的。
    b.setColor(red)
    b.clearChildren()
    ViewC c3 = new ViewC(...)
    b.add(c3)
    但是在声明式的UI系统中,view是不可变的,所以所有的视图都是轻量级的“蓝图”,当需要改变的时候,就会重新构建这个view(Flutter中一遍就是StatefulWidget组件通过State中调用setState()方法):
    return ViewB(
      color: red,
      child: ViewC(...),
    )
    至于那种模式好,效率高当然是各家之言,等到我足够体验之后才能做出自己的判断。

 

Hello world!    

//使用了material的包,Flutter还提供一个cupertion包,用于表示谷歌和苹果两种界面风格
//当然我们完全可以自定义自己的风格
import 'package:flutter/material.dart';
//引入了一个三方库 english_words ,需要在pubspec.yaml中的dependencies: 下面添加 english_words: ^3.1.0
import 'package:english_words/english_words.dart';

//main是dart的主方法,主方法很简单,调用系统方法runApp,运行一个App
void main() => runApp(MyApp()); 

//MyApp 就是我们的app了,它继承与StatelessWidget组件
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) { //build是组件类的基本方法,用于构建这个组件的显示样式
    final wordPair = WordPair.random();
    return MaterialApp( //一个MaterialApp widget
      title: 'Welcome to Flutter',
      home: Scaffold( //一个Scaffold widget相当于主界面,包含一个组件树
        appBar: AppBar( //标题栏组件
          title: Text('Welcome to Flutter IOS'),
        ),
        body: Center( //center组件,居中显示
          child: Text(wordPair.asPascalCase),
        ),
      ),
    );
  }
}

    这段代码以及注释希望能够让你对Flutter有一个初步映像,至于其中包含的上面appBar啊Center啊这些组件,真的是在开发过程中逐步积累的过程,并不是入门时的重点。    

Widget

    组件widget分为两种,一种不不可变的StatelessWidget他内部的变量都是final类型的,所以是属性不可变的组件。另一种是StatefulWidget组件。

    实现StatefulWidget至少需要两个类:一个StatefulWidget类 2)State<?>类的实例。 StatefulWidget类本身是不可变的,但State类在窗口小部件的生命周期内持久存在。

    扩展一下上面代码

//使用了material的包,Flutter还提供一个cupertion包,用于表示谷歌和苹果两种界面风格
//当然我们完全可以自定义自己的风格
import 'package:flutter/material.dart';
//引入了一个三方库 english_words ,需要在pubspec.yaml中的dependencies: 下面添加 english_words: ^3.1.0
import 'package:english_words/english_words.dart';

//main是dart的主方法,主方法很简单,调用系统方法runApp,运行一个App
void main() => runApp(MyApp()); 

//MyApp 就是我们的app了,它继承与StatelessWidget组件
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) { //build是组件类的基本方法,用于构建这个组件的显示样式
    return MaterialApp( //一个MaterialApp widget
      title: 'Welcome to Flutter',
      home: Scaffold( //一个Scaffold widget相当于主界面,包含一个组件树
        appBar: AppBar( //标题栏组件
          title: Text('Welcome to Flutter IOS'),
        ),
        body: Center( //center组件,居中显示
          child: RandomWords() //使用StatefulWidget组件
        ),
      ),
    );
  }
}

/*
 * 为了实现StatefulWidget,必须要有一个State类,用于帮助StatefulWidget build它的显示样式。
 * 实际上,大多数的业务逻辑都是在State中进行处理的。
 */
class RandomWordsState extends State<RandomWords>{
  @override
  Widget build(BuildContext context) {
    final wordPair = WordPair.random();
    return Text(wordPair.asPascalCase);
  }
}

/*
 * 定义一个用于显示随机单词的组件,这个组件是一个StatefulWidget组件,所以我们必须要提供一个State<RandomWords>的类
 * StatefulWidget 内部必须重写createState方法。他的widget的build方法交给这个State去写。
 */
class RandomWords extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return RandomWordsState();
  }
}

扩展成无限滑动的list

    首先下面代码的主要目的并不是让我们掌握Flutter中list的具体用法,个人觉得应该亲自去写一下代码,知道这里在干什么,去了解Flutter的代码构成方式和体会“一切都是组件”的含义。

//使用了material的包,Flutter还提供一个cupertion包,用于表示谷歌和苹果两种界面风格
//当然我们完全可以自定义自己的风格
import 'package:flutter/material.dart';
//引入了一个三方库 english_words ,需要在pubspec.yaml中的dependencies: 下面添加 english_words: ^3.1.0
import 'package:english_words/english_words.dart';

//main是dart的主方法,主方法很简单,调用系统方法runApp,运行一个App
void main() => runApp(MyApp()); 

//MyApp 就是我们的app了,它继承与StatelessWidget组件
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) { //build是组件类的基本方法,用于构建这个组件的显示样式
    return MaterialApp( //一个MaterialApp widget
      title: 'Welcome to Flutter',
      home: RandomWords(), //主界面是一个RandomWords类型的组件
    );
  }
}

/*
 * 为了实现StatefulWidget,必须要有一个State类,用于帮助StatefulWidget build它的显示样式。
 * 实际上,大多数的业务逻辑都是在State中进行处理的。
 */
class RandomWordsState extends State<RandomWords>{
  final _suggestions = <WordPair>[];
  final _biggerFont = const TextStyle(fontSize: 18.0);

  /*
   * 用于创建一个ListView组件
   */
  Widget _buildSuggestions(){
    //listview的builder工厂方法
    return ListView.builder(padding: const EdgeInsets.all(16.0),
      itemBuilder: (context,i){  /* dart写法,类似于匿名类和lambda */
        //如果是基数,返回分割线
        if(i.isOdd) return Divider();
        final index = i ~/ 2; //i除以2 并返回整数结果
        if(index >= _suggestions.length){
          _suggestions.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_suggestions[index]);
      }, 
    );
  }
  /*
   * 创建listview中的每一个item,每个item都是一个组件
   */
  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }

  /*
   * 创建RandomWords组件的界面展示。 
   */
  @override
  Widget build(BuildContext context) {
    return Scaffold (
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }
}

/*
 * 定义一个用于显示随机单词的组件,这个组件是一个StatefulWidget组件,所以我们必须要提供一个State<RandomWords>的类
 * StatefulWidget 内部必须重写createState方法。他的widget的build方法交给这个State去写。
 */
class RandomWords extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return RandomWordsState();
  }
}

添加页面跳转和点击

    继续改造上面的代码,添加了随机单词标星这样的操作。并且能够进行页面跳转。

//使用了material的包,Flutter还提供一个cupertion包,用于表示谷歌和苹果两种界面风格
//当然我们完全可以自定义自己的风格
import 'package:flutter/material.dart';
//引入了一个三方库 english_words ,需要在pubspec.yaml中的dependencies: 下面添加 english_words: ^3.1.0
import 'package:english_words/english_words.dart';

//main是dart的主方法,主方法很简单,调用系统方法runApp,运行一个App
void main() => runApp(MyApp()); 

//MyApp 就是我们的app了,它继承与StatelessWidget组件
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) { //build是组件类的基本方法,用于构建这个组件的显示样式
    return MaterialApp( //一个MaterialApp widget
      title: 'Welcome to Flutter',
      home: RandomWords(), //主界面是一个RandomWords类型的组件
      theme: new ThemeData(primaryColor: Colors.white), //修改app主题
    );
  }
}

/*
 * 为了实现StatefulWidget,必须要有一个State类,用于帮助StatefulWidget build它的显示样式。
 * 实际上,大多数的业务逻辑都是在State中进行处理的。
 */
class RandomWordsState extends State<RandomWords>{
  final _suggestions = <WordPair>[];
  final _biggerFont = const TextStyle(fontSize: 18.0);
  final Set<WordPair> _saved = new Set<WordPair>(); //用于存储已经点赞的名字
  /*
   * 用于创建一个ListView组件
   */
  Widget _buildSuggestions(){
    //listview的builder工厂方法
    return ListView.builder(padding: const EdgeInsets.all(16.0),
      itemBuilder: (context,i){  /* dart写法,类似于匿名类和lambda */
        //如果是基数,返回分割线
        if(i.isOdd) return Divider();
        final index = i ~/ 2; //i除以2 并返回整数结果
        if(index >= _suggestions.length){
          _suggestions.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_suggestions[index]);
      }, 
    );
  }
  /*
   * 创建listview中的每一个item,每个item都是一个组件
   */
  Widget _buildRow(WordPair pair) {
    final bool alreadySaved = _saved.contains(pair); //记录是否已经标记过
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: Icon(alreadySaved? Icons.favorite : Icons.favorite_border,
            color: alreadySaved ? Colors.red:null,),//创建一个星形icon
      //icon点击事件
      onTap: (){setState(() { //使用setState来更新list中item的状态,setState会先运行下面代码,然后再通知list更改item
              if(alreadySaved){
                _saved.remove(pair);
              }else{
                _saved.add(pair);
              }
            });},
    );
  }
  /*
   * 创建RandomWords组件的界面展示。 
   */
  @override
  Widget build(BuildContext context) {
    return Scaffold (
      appBar: AppBar(
        title: Text('Startup Name Generatorrrrrr'),
        //为app bar增加左上按钮
        actions: <Widget>[IconButton(icon: const Icon(Icons.list),onPressed: _pushSaved)],
      ),
      body: _buildSuggestions(),
    );
  }
  
  /*
   * appbar 左上按钮点击事件。使用Navigator 跳转到新页面
   * Navigator 是Flutter中的路由管理器,通过push进行跳转,通过remove进行返回
   */
  void _pushSaved(){
    //在路由管理器 Navigator中push一个新的路由
    //这个路由是一个页面路由,通过builder构建这个页面
    Navigator.of(context).push(MaterialPageRoute<void>(builder: (context){
      //dart语法,每一个被标星的单词都会生成一个ListTile组件
      final Iterable<ListTile> tiles = _saved.map(
        (pair){
          return new ListTile(
            title: new Text(pair.asPascalCase,style:_biggerFont),
          );
        }
      );
      //在tiles组件之间插入分割线
      final List<Widget> divided = ListTile.divideTiles(context: context,tiles: tiles).toList();
      return new Scaffold(
        appBar: new AppBar(title: const Text('Saved Suggestions'),),
        body: new ListView(children: divided,),//生成listview
      );
    }));
  }
}

/*
 * 定义一个用于显示随机单词的组件,这个组件是一个StatefulWidget组件,所以我们必须要提供一个State<RandomWords>的类
 * StatefulWidget 内部必须重写createState方法。他的widget的build方法交给这个State去写。
 */
class RandomWords extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return RandomWordsState();
  }
}

 

结语

    基本上所有的分析都写在注释中,所以文章本身并没有多少文字,都是贴代码。如果能够跟着上面的步骤,将代码好好读一遍,那么应该就基本上算是初步了解了Flutter的代码构成。当然这只是万里长征的第一步,更多的资源可以参考这里

    另外上面的代码并没有进行非常好的代码结构处理,而是一直在dart提供的函数式编程能力。这样就导致代码层次嵌套很多(如果老老实实用局部变量,就能够极大的减少嵌套),对后续阅读产生困扰,所以语法糖这种东西,并不是在任何时候都讨喜的。

转载于:https://my.oschina.net/zzxzzg/blog/2962136

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
flutter_downloader是一个用于在Flutter应用程序中进行文件下载的插件。它提供了一种简单而强大的方式来管理和监控文件下载任务。 使用flutter_downloader,你可以轻松地添加文件下载功能到你的Flutter应用程序中。它支持多个平台,包括Android和iOS,并且提供了一组易于使用的API来管理下载任务。 要使用flutter_downloader,首先需要在你的Flutter项目中添加依赖。在pubspec.yaml文件中,添加以下内容: ``` dependencies: flutter_downloader: ^1.6.0 ``` 然后运行`flutter pub get`命令来获取依赖。 接下来,在你的代码中导入flutter_downloader包,并使用它来创建和管理下载任务。你可以使用`FlutterDownloader.enqueue`方法来创建一个下载任务,并传递下载链接、保存路径等参数。你还可以使用`FlutterDownloader.open`方法来打开已下载的文件。 以下是一个简单的示例代码,演示了如何使用flutter_downloader进行文件下载: ```dart import 'package:flutter/material.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('File Downloader'), ), body: Center( child: RaisedButton( child: Text('Download File'), onPressed: () { _startDownload(); }, ), ), ), ); } void _startDownload() async { String url = 'https://example.com/file.pdf'; String savedDir = '/storage/emulated/0/Download'; await FlutterDownloader.enqueue( url: url, savedDir: savedDir, showNotification: true, openFileFromNotification: true, ); } } ``` 这是一个简单的示例,当用户点击按钮时,会触发文件下载任务。下载的文件将保存在指定的目录中,并且会显示下载通知。用户可以通过通知来打开已下载的文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值