我们要开发一款懒加载和无线滚动元素的应用。

项目github地址:https://github.com/youngchou1997/flutter_app
**
基于上一篇文章的内容,我们有了一个APP的框架,包含顶栏和内容组件。
接下来我们使用外部包。

安装外部包

在Flutter中,使用 pub 管理包。我们搜索english_words包,这个包其中包含几千个最常用的英语单词和一些实用功能。
可以在这里看看这个包的情况:
https://pub.dev/flutter/packages?q=english_words

pubspec文件管理Flutter应用程序的资产和依赖项。在pubspec.yaml中,将english_words(3.1.5或更高版本)添加到依赖项列表:

  1. dependencies:
  2. flutter:
  3. sdk: flutter
  4. # The following adds the Cupertino Icons font to your application.
  5. # Use with the CupertinoIcons class for iOS style icons.
  6. cupertino_icons: ^0.1.2
  7. english_words: ^3.1.5

选中pubspec.yaml文件,然后右击出现菜单,点击get packages选项

image.png
image.png

或者在终端中运行flutter pub get命令,包就会被拉取存储到项目中,我们就可以使用了。

image.png

可能遇到的问题

pub被墙,需要开代理,除此外,
环境:shadowsocks、windows
本地ss端口设置(这里1080)
cmd命令行:(不用socks5)(临时设置)(也可放置环境变量)
set http_proxy=http://127.0.0.1:1080
set https_proxy=http://127.0.0.1:1080
ps:一定要用cmd命令行,千万别用powershell !!!
简易测试命令:curl https://www.google.com(别用ping)
image.png
这样就会发现能够下载成功了。如果期间重复运行flutter命令多次,可能出现锁死情况,可以去\bin\cache目录,删除lockfile文件,接下来,引入包并使用。

使用外部包

在main.dart中添加import 'package:english_words/english_words.dart';

  1. Widget build(BuildContext context) {
  2. final wordPair = WordPair.random(); // WorPaid.random() 方法随机生成一个单词
  3. return Scaffold(
  4. appBar: AppBar(
  5. title: Text(widget.title),
  6. ),
  7. body: Center(
  8. child: Column(
  9. mainAxisAlignment: MainAxisAlignment.center,
  10. children: <Widget>[
  11. Text(
  12. '今日天气',
  13. ),
  14. Text(
  15. '$_counter',
  16. style: Theme.of(context).textTheme.display1,
  17. ),
  18. Text(wordPair.asPascalCase), // 帕斯卡类型单词,首字母大写的驼峰式命名方法
  19. ],
  20. ),
  21. ),
  22. floatingActionButton: FloatingActionButton(
  23. onPressed: _incrementCounter,
  24. tooltip: 'Increment',
  25. child: Icon(Icons.add),
  26. ),
  27. );
  28. }
  29. }

使用了热更新方式就会看到每次保存后,界面中单词都会变化。

image.pngimage.png

创建使用有状态组件

无状态组件(stateless)意味着组件的属性是不可被改变的,组件属性是最终状态。
有状态窗口小部件维护一个状态,这个状态可能在部件生命周期内发生更改。实现有状态窗口小部件至少需要两个类:1)一个StatefulWidget类,它创建一个State类的实例;2)State类的实例。StatefulWidget类本身是不可变的,但State类在组件生命周期中存在是可变的。
接下来,我们创建一个有状态组件,它将被包含于无状态组件当中。我们通过直接调用这个任意单词组件生成函数来生成一个任意单词组件,从而取代之前的语句。

1. 添加代码到 main.dart 底部

  1. class RandomWords extends StatefulWidget {
  2. @override
  3. RandomWordsState createState() => RandomWordsState();
  4. }
  5. class RandomWordsState extends State<RandomWords> {
  6. @override
  7. Widget build(BuildContext context) {
  8. final wordPair = WordPair.random();
  9. return Text(wordPair.asPascalCase);
  10. }
  11. }

声明RandomWords小部件的有状态的State类实例RandomWordsState。RandomWordsState依赖于RandomWords。State声明表明我们正在使用专门用于RandomWords的通用State类。RandomWordsState中存放组件的逻辑和状态,维护这个对象就能够维护组件的状态。

2.修改代码

如下方代码块所示,将第3行和第20行代码对应在main.dart的部分删掉,然后添加21行的组件方法调用语句生成一个组件。

  1. @override
  2. Widget build(BuildContext context) {
  3. - final wordPair = WordPair.random();
  4. return Scaffold(
  5. appBar: AppBar(
  6. title: Text(widget.title),
  7. ),
  8. body: Center(
  9. child: Column(
  10. mainAxisAlignment: MainAxisAlignment.center,
  11. children: <Widget>[
  12. Text(
  13. // 'You have pushed the button this many times:',
  14. '今日天气',
  15. ),
  16. Text(
  17. '$_counter',
  18. style: Theme.of(context).textTheme.display1,
  19. ),
  20. - Text(wordPair.asPascalCase), // 帕斯卡类型单词,首字母大写的驼峰式命名方法
  21. + RandomWords()
  22. ],
  23. ),
  24. ),
  25. floatingActionButton: FloatingActionButton(
  26. onPressed: _incrementCounter,
  27. tooltip: 'Increment',
  28. child: Icon(Icons.add),
  29. ), // This trailing comma makes auto-formatting nicer for build methods.
  30. );
  31. }

3.结果

如果是热调试方式连接了设备,我们就能够看到,修改后的代码和之前的效果一样,我们用到了有状态部件。

创建一个无限滚动列表视图组件

接下来我们将继续创建一个无限滚动的列表视图组件,简单描述就是,这个组件可以一直滚动,不停添加新的条目。

  1. import 'package:flutter/material.dart';
  2. import 'package:english_words/english_words.dart';
  3. void main() => runApp(MyApp());
  4. class MyApp extends StatelessWidget {
  5. // 应用的根组件
  6. @override
  7. Widget build(BuildContext context) {
  8. return MaterialApp(
  9. title: '欢迎使用新青柚天气',
  10. theme: ThemeData(
  11. primarySwatch: Colors.blue,
  12. ),
  13. home: RandomWords(),
  14. );
  15. }
  16. }
  17. class RandomWordsState extends State<RandomWords> {
  18. final _suggestions = <WordPair>[];
  19. // 设置字体属性
  20. final _biggerFont = const TextStyle(fontSize: 18.0);
  21. Widget _buildSuggestions() {
  22. return ListView.builder(
  23. padding: const EdgeInsets.all(16.0),
  24. itemBuilder: /*1*/ (context, i) {
  25. if (i.isOdd) return Divider(); /*2*/
  26. final index = i ~/ 2; /*3*/
  27. if (index >= _suggestions.length) {
  28. _suggestions.addAll(generateWordPairs().take(10)); /*4*/
  29. }
  30. return _buildRow(_suggestions[index]);
  31. });
  32. }
  33. Widget _buildRow(WordPair pair) {
  34. return ListTile(
  35. title: Text(
  36. pair.asPascalCase,
  37. style: _biggerFont,
  38. ),
  39. );
  40. }
  41. Widget build(BuildContext context) {
  42. return Scaffold(
  43. appBar: AppBar(
  44. title: Text('单词本')
  45. ),
  46. body: _buildSuggestions()
  47. );
  48. }
  49. }
  50. class RandomWords extends StatefulWidget {
  51. @override
  52. RandomWordsState createState() => RandomWordsState();
  53. }

至此,我们完成了这个组件的使用。

Tips

  1. VS Code 命令中输入 flutter Toggle Debug Paint,就能看到APP的布局线框。
  2. 我遇到的问题分享:
    1. 我工作时使用公司的git进行版本管理,平时自己的项目用github,那该如何让两个账户互通呢?

我自己想了个最简单的办法,公司项目用git命令行操作,自己的项目使用github桌面客户端管理,快捷方便地解决了我的问题。