Flutter 实战:构建跨平台应用

news2024/11/19 20:21:52

文章目录

  • 一、简介
  • 二、开发环境搭建
  • 三、实战案例:开发一个简单的天气应用
    • 1. 项目创建
    • 2. 界面设计
    • 3. 数据获取
    • 4. 实现数据获取和处理
    • 5. 界面展示
    • 6. 添加动态效果和交互
    • 7. 添加网络错误处理
    • 8. 添加刷新功能
    • 9. 添加定位功能
    • 10. 添加通知功能
    • 11. 添加数据持久化功能
  • 《Flutter小白开发——跨平台客户端应用开发学习路线》
    • 内容简介
    • 作者简介
    • 目录


一、简介

Flutter是由Google开发的一款开源移动应用开发框架,它可以帮助开发者在iOS和Android平台上快速、高效地开发应用。Flutter使用Dart语言作为开发语言,具有跨平台兼容性高、开发效率快、性能优异等特点。本文将通过实战案例,介绍如何使用Flutter构建跨平台应用。

二、开发环境搭建

在开始Flutter开发之前,需要先安装Flutter SDK和开发环境。可以按照Flutter官方文档的指引,下载并安装Flutter SDK,以及配置开发环境。

三、实战案例:开发一个简单的天气应用

本案例将通过使用Flutter开发一个简单的天气应用,介绍Flutter的开发流程和常用组件。

1. 项目创建

在终端中进入要创建项目的目录,然后运行以下命令创建一个新的Flutter项目:

flutter create weatherapp

2. 界面设计

进入项目目录,打开lib/main.dart文件,可以看到默认的Flutter界面代码。在这个文件中,我们可以编写应用的界面和逻辑代码。为了让应用更加美观和易用,我们可以使用Flutter提供的各种组件和布局。比如,我们可以使用MaterialApp组件来设置应用的主题和导航,使用Container组件来设置容器和背景,使用Text组件来显示文本信息,等等。

3. 数据获取

为了让天气应用能够实时获取并显示天气信息,我们需要使用网络请求来获取数据。在Flutter中,我们可以使用http库来发送HTTP请求。在pubspec.yaml文件中添加以下代码来引入http库:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.12.0

然后运行以下命令来更新依赖:

flutter pub get

4. 实现数据获取和处理

main.dart文件中,我们可以使用HttpClient类来发送HTTP请求,获取天气数据。然后,我们可以使用JsonDecoder类将JSON数据解析为Dart对象,方便后续操作。示例代码如下:

import 'package:http/http.dart' as http;
import 'package:json_annotation/json_annotation.dart';
import 'package:weatherapp/models/weather.dart';

void main() async {
  // 发送HTTP请求,获取天气数据
  final response = await http.get('https://api.example.com/weather');

  // 解析JSON数据
  final jsonData = jsonDecode(response.body);
  final weatherData = Weather.fromJson(jsonData);

  // 处理天气数据,如显示在界面上
  // ...
}

在上面的代码中,我们使用http.get方法发送GET请求,获取天气数据的JSON字符串。然后,我们使用jsonDecode方法将JSON字符串解析为Dart对象,方便后续操作。最后,我们使用Weather.fromJson方法将JSON数据解析为Weather对象,方便后续操作。

5. 界面展示

最后,我们可以在界面上展示天气数据。在Flutter中,我们可以使用各种组件和布局来展示数据。比如,我们可以使用Text组件来显示天气温度和天气情况,使用ListView组件来展示未来几天的天气预报,等等。示例代码如下:

import 'package:flutter/material.dart';
import 'package:weatherapp/models/weather.dart';

class WeatherApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Weather App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Weather App'),
        ),
        body: Center(
          child: Text('Temperature: ${weatherData.temperature}°C'),
          child: Text('Weather: ${weatherData.weather[0].description}'),
        ),
      ),
    );
  }
}

在上面的代码中,我们定义了一个WeatherApp组件作为应用的主界面。在这个组件中,我们使用MaterialApp组件来设置应用的主题和导航,使用Scaffold组件来设置应用的布局和导航栏,使用AppBar组件来设置导航栏的标题和样式,使用Center组件来设置布局的中心点,使用Text组件来显示天气温度和天气情况。需要注意的是,在上面的代码中,我们使用了名为weatherData的变量来保存天气数据,方便后续操作。

6. 添加动态效果和交互

为了让天气应用更加生动和易用,我们可以添加一些动态效果和交互。比如,我们可以使用Flutter提供的AnimationController类来控制动画的播放和速度,使用Hero组件来实现页面之间的转场动画,使用RaisedButton组件来添加交互按钮,等等。示例代码如下:

import 'package:flutter/material.dart';
import 'package:weatherapp/models/weather.dart';

class WeatherApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Weather App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Weather App'),
        ),
        body: Center(
          child: Text('Temperature: ${weatherData.temperature}°C'),
          child: Text('Weather: ${weatherData.weather[0].description}'),
          child: Hero(
            tag: 'weather-app',
            child: Container(
              color: Colors.lightBlueAccent,
              child: ListView.builder(
                itemCount: weatherData.weather.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    title: Text('${weatherData.weather[index].description}'),
                    leading: Icon(Icons.ac_unit),
                    trailing: Icon(Icons.access_time),
                    onTap: () {
                      // 跳转到详细页面
                    },
                  );
                },
              ),
            ),
          ),
        ),
      ),
    );
  }
}

在上面的代码中,我们使用Hero组件来实现页面之间的转场动画。同时,我们使用ListView.builder组件来展示未来几天的天气预报,使用ListTile组件来定义每个天气的标题、图标和操作按钮。当用户点击操作按钮时,可以跳转到详细页面,展示该天气的详细信息。需要注意的是,在上面的代码中,我们使用了名为weatherData的变量来保存天气数据,方便后续操作。

7. 添加网络错误处理

在实现天气应用时,我们需要考虑到网络错误的情况。当网络连接失败或者请求超时时,我们需要给出相应的错误提示,以便用户了解情况。在Flutter中,我们可以使用try-catch语句来捕获异常,并进行相应的错误处理。示例代码如下:

void main() async {
  try {
    // 发送HTTP请求,获取天气数据
    final response = await http.get('https://api.example.com/weather');

    // 解析JSON数据
    final jsonData = jsonDecode(response.body);
    final weatherData = Weather.fromJson(jsonData);

    // 处理天气数据,如显示在界面上
    // ...
  } catch (error) {
    // 发生异常,进行错误处理
    print(error);
    // 显示网络错误提示,例如:重新加载或检查网络连接
  }
}

在上面的代码中,我们使用try-catch语句来捕获异常。当发生异常时,我们打印错误信息,并可以进行相应的错误处理,例如:显示网络错误提示,让用户重新加载或者检查网络连接。

8. 添加刷新功能

为了让天气应用更加易用,我们可以添加刷新功能。当用户需要更新天气数据时,可以通过手动刷新来获取最新的天气数据。在Flutter中,我们可以使用RefreshIndicator组件来实现刷新功能。示例代码如下:

void main() async {
  // 初始化变量,记录是否已经加载过数据
  bool hasLoadedData = false;
  
  runApp(MaterialApp(
    title: 'Weather App',
    home: Scaffold(
      appBar: AppBar(title: Text('Weather App')),
      body: Center(
        child: RefreshIndicator(
          onRefresh: () async {
            if (!hasLoadedData) {
              // 第一次加载数据,直接获取天气数据并显示在界面上
              final response = await http.get('https://api.example.com/weather');
              final weatherData = Weather.fromJson(jsonDecode(response.body));
              // 处理天气数据,如显示在界面上
              hasLoadedData = true; // 标记已经加载过数据,避免重复加载
            } else {
              // 非第一次加载数据,执行刷新操作(例如:重新获取天气数据并显示在界面上)
              // ...
            }
          },
          child: Column(children: [ /* 显示天气数据的组件 */ ]),
        ),
      ),
    ),
  ));
}

在上面的代码中,我们使用RefreshIndicator组件来实现刷新功能。当用户手动刷新时,会触发onRefresh回调函数。在该函数中,我们可以执行相应的刷新操作,例如:重新获取天气数据并显示在界面上。需要注意的是,我们在onRefresh回调函数中判断了是否已经加载过数据。如果是第一次加载数据,我们会直接获取天气数据并显示在界面上;否则,我们会执行刷新操作(例如:重新获取天气数据并显示在界面上)。这样就可以避免重复加载数据和不必要的刷新操作。

9. 添加定位功能

为了让天气应用更加个性化,我们可以添加定位功能。通过获取用户的地理位置信息,我们可以获取用户所在地的天气数据,并为其提供更准确的天气预报服务。在Flutter中,我们可以使用geolocator插件来获取用户的地理位置信息。示例代码如下:

首先,在pubspec.yaml文件中添加geolocator插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  geolocator: ^5.1.1

然后,在代码中使用geolocator插件来获取用户的地理位置信息:

import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';

class WeatherApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Weather App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(title: Text('Weather App')),
        body: Center(
          child: Text('Temperature: ${weatherData.temperature}°C'),
          child: Text('Weather: ${weatherData.weather[0].description}'),
          child: Hero(
            tag: 'weather-app',
            child: Container(
              color: Colors.lightBlueAccent,
              child: ListView.builder(
                itemCount: weatherData.weather.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                    title: Text('${weatherData.weather[index].description}'),
                    leading: Icon(Icons.ac_unit),
                    trailing: Icon(Icons.access_time),
                    onTap: () {
                      // 跳转到详细页面
                    },
                  );
                },
              ),
            ),
          ),
        ),
      ),
    );
  }
}

10. 添加通知功能

为了提醒用户天气变化或者重要通知,我们可以添加通知功能。在Flutter中,我们可以使用flutter_local_notifications插件来发送本地通知。示例代码如下:

首先,在pubspec.yaml文件中添加flutter_local_notifications插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_local_notifications: ^8.0.0

然后,在代码中使用flutter_local_notifications插件来发送通知:

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

class WeatherApp extends StatelessWidget {
  static void showNotification(BuildContext context, String message) {
    showLocalNotification(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Weather Alert'),
          content: Text(message),
          actions: [
            TextButton(
              child: Text('Dismiss'),
              onPressed: () {},
            ),
          ],
        );
      },
      notificationBuilder: (BuildContext context, int notificationId) {
        return SimpleNotification(title: 'Weather Alert', description: 'Check out the weather forecast!', color: Colors.lightBlueAccent);
      },
    );
  }
}

11. 添加数据持久化功能

为了让天气应用在用户重新打开时仍然保留之前的数据,我们可以添加数据持久化功能。在Flutter中,我们可以使用shared_preferences插件来保存和读取用户的设置和数据。示例代码如下:

首先,在pubspec.yaml文件中添加shared_preferences插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.0.5

然后,在代码中使用shared_preferences插件来保存和读取数据:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class WeatherApp extends StatefulWidget {
  @override
  _WeatherAppState createState() => _WeatherAppState();
}

class _WeatherAppState extends State<WeatherApp> {
  String _temperature = '';
  String _weather = '';
  bool _isFavorited = false;

  @override
  void initState() {
    super.initState();
    readData();
  }

  void readData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _temperature = prefs.getString('temperature');
    _weather = prefs.getString('weather');
    _isFavorited = prefs.getBool('isFavorited');
  }

  void saveData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setInt('temperature', 25); // 这里的键值需要和读取时的保持一致,否则无法保存成功。同时这里的value是int类型,需要转为String保存。
    prefs.setString('weather', 'Sunny');
    prefs.setBool('isFavorited', true);
  }
}

《Flutter小白开发——跨平台客户端应用开发学习路线》

在这里插入图片描述

内容简介

《Flutter小白开发——跨平台客户端应⽤开发学习路线》以移动平台(iOS/安卓)与Web 平台为例,系统地介绍如何基于Flutter 框架开发跨平台的应用。

《Flutter小白开发——跨平台客户端应⽤开发学习路线》分为三大部分,共27 章。第一部分(第1~4 章)主要介绍开发前要做的准备工作,包括安装命令行界面、开发环境,熟悉Dart 语言和包管理知识;第二部分(第5~14 章)带领大家熟悉和理解Flutter框架,掌握Flutter 应用开发的基础知识;第三部分(第15~27 章)是Flutter 实践,结合服务端应用接口,实现一些真实应用里经常用到的界面,并将做好的应用发布到应用商店。

《Flutter小白开发——跨平台客户端应⽤开发学习路线》提供了一套系统、全面的训练任务,从易到难,轻松有趣。从准备开发工具与开发环境开始,熟悉程序语言,了解应用框架,直到具体实践与应用分发,引领大家逐步掌握Flutter 应用框架的使用技巧,获得开发移动端应用的基础能力,对于初学者来说非常友好。

作者简介

王皓,宁皓网作者,独立开发者,自学应用开发十年有余,创作过数百万字的应用技术内容与数百小时的技术视频,内容覆盖Web技术、客户端与服务端应用开发,内容风格简单有效,逻辑清晰,帮助无数技术爱好者掌握了应用开发技能。

目录

第一部分 开发准备

第1 章 准备开发 2

1.1 命令行界面 2

1.1.1 任务:Windows 系统下准备命令行界面Cmder 2

1.1.2 任务:在macOS 系统下准备命令行界面Terminal 3

1.1.3 任务:熟悉基本命令 3

1.1.4 理解环境变量目录 5

1.1.5 知道命令来自哪里 5

1.1.6 命令行工具的帮助信息 6

1.1.7 命令行界面的配置文件 6

1.2 代码编辑器 7

1.3 源代码管理 82章 开发环境 9

2.1 下载开发工具包 9

2.1.1 任务:macOS 系统下安装Flutter 9

2.1.2 任务:Windows 系统下安装Flutter 10

2.1.3 任务:配置使用国内镜像 11

2.2 准备iOS 与macOS 应用开发环境 11

2.2.1 任务:安装Rosetta 12

2.2.2 任务:安装Homebrew 12

2.2.3 任务:安装与准备Xcode 12

2.3 准备Android平台应用开发环境 13

2.4 准备设备模拟器 14

2.5 准备Web 应用开发环境 15

2.6 准备代码编辑器VSCode 15

2.7 创建Flutter 项目 16

2.7.1 任务:创建并运行Flutter 项目 16

2.7.2 任务:清理项目与源代码管理 18

2.8 问题与思考 183章 熟悉Dart 语言 21

3.1 准备工作 21

3.2 变量 22

3.2.1 var 22

3.2.2 final 22

3.2.3 const 23

3.2.4 理解var、final 与const 的区别 23

3.3 类型 25

3.4 内置类型 25

3.4.1 字符串 25

3.4.2 数字 26

3.4.3 布尔值 26

3.4.4 列表 27

3.4.5 集合 27

3.4.6 映射 28

3.5 函数 28

3.5.1 创建函数 29

3.5.2 执行函数 29

3.5.3 函数参数 29

3.5.4 函数有多个参数 29

3.5.5 有名字的参数 30

3.5.6 必填参数 30

3.5.7 参数默认值 31

3.5.8 函数返回值 31

3.6 流程控制 31

3.6.1 if 语句 32

3.6.2 switch 语句 32

3.7 异常 34

3.7.1 抛出异常(throw34

3.7.2 捕获异常(catch/on) 34

3.835

3.8.1 定义一个类 36

3.8.2 实例化一个类 36

3.8.3 属性 36

3.8.4 构造方法 37

3.8.5 this 关键字 37

3.8.6 带名字的构造方法 38

3.8.7 方法 38

3.8.8 继承 39

3.8.9 类属性 39

3.8.10 类方法 40

3.9 泛型 40

3.1041

3.10.1 使用内置库 41

3.10.2 指定库前缀 41

3.10.3 导入部分库 42

3.10.4 导入开发者个人库里的资源 42

3.11 Future 42

3.11.1 定义异步函数 43

3.11.2 使用异步函数提供的值 43

3.11.3 处理异步函数遇到的错误 444章 包管理 45

4.1 包(Package) 45

4.2 pubspec.yaml 文件 45

4.3 安装包 46

4.3.1 解决包依赖问题 46

4.3.2 dependencies 属性 46

4.3.3 版本号 47

4.3.4 pubspec.lock 文件 47

4.3.5 package_config.json 文件 47

4.4 使用包 48

4.5 升级包 48

第二部分 Flutter基础

第5章 基本部件 52

5.1 准备 52

5.1.1 任务:准备项目(widget) 52

5.1.2 任务:准备应用入口 52

5.2 小部件(Widget) 53

5.3 自定义一个无状态的小部件 54

5.4 Text(文本) 56

5.5 RichText(富文本) 58

5.6 Image(图像) 59

5.6.1 任务:显示资源包里的图像 60

5.6.2 任务:显示来自网络的图像 61

5.6.3 任务:调整图像的显示 62

5.7 Container(容器) 63

5.7.1 任务:使用Container 小部件 64

5.7.2 任务:装饰容器 66

5.8 整理项目 696章 页面结构 70

6.1 准备项目(page-structure) 70

6.2 MaterialApp 70

6.2.1 任务:创建Material 应用 70

6.2.2 任务:使用图标(Icon) 71

6.2.3 任务:使用按钮(ElevatedButton) 72

6.2.4 任务:定制应用的主题样式 73

6.3 Scaffold(页面结构) 75

6.4 AppBar(应用栏) 76

6.5 TabBar(标签栏) 77

6.6 BottomNavigationBar(底部导航栏) 79

6.6.1 任务:设置底部导航栏 79

6.6.2 任务:把App 转换成有状态小部件(StatefulWidget) 80

6.6.3 任务:单击底部导航栏项目,切换当前活动项目 81

6.6.4 任务:单击底部导航栏项目,切换显示小部件 82

6.6.5 任务:单击底部导航栏项目,动态显示或隐藏AppBar 83

6.7 FloatingActionButton(漂浮动作按钮) 84

6.8 整理项目 857章 定义部件 86

7.1 准备 86

7.1.1 任务:准备项目(define-widget) 86

7.1.2 任务:配置VSCode 编辑器代码片断 87

7.2 AppPageHeader(页面头部) 88

7.3 AppLogo(应用标志) 89

7.4 AppPageMain(页面主体) 90

7.5 PostIndex(内容索引) 93

7.6 AppPageBottom(页面底部) 94

7.7 AppFloatingActionButton(漂浮动作按钮) 96

7.8 目录结构 97

7.9 小部件树 97

7.10 整理项目 988章 弹窗对话 99

8.1 准备项目(modal-dialog) 99

8.2 BottomSheet(底部面板) 99

8.2.1 任务:显示页面底部面板 99

8.2.2 任务:用漂浮动作按钮显示与关闭底部面板 101

8.3 AlertDialog(警告对话框) 103

8.4 SnackBar(消息提示栏) 105

8.5 Drawer(边栏抽屉) 106

8.5.1 任务:使用边栏抽屉 107

8.5.2 任务:设置边栏抽屉上显示的内容(ListView 与ListTile) 108

8.6 PopupMenuButton(弹出菜单按钮) 111

8.7 整理项目 1139章 页面布局 114

9.1 准备 114

9.1.1 任务:准备项目(layout) 114

9.1.2 任务:准备练习页面 114

9.2 约束 116

9.2.1 任务:理解小部件的约束 116

9.2.2 任务:准备一个布局演示项目小部件 119

9.2.3 任务:使用安全区域(SafeArea)和尺寸盒子(SizedBox) 120

9.3 Align(对齐) 121

9.4 Column(栏/列) 122

9.5 Row(行/排) 124

9.6 Expanded(扩展空间) 126

9.7 Stack(堆) 127

9.8 Positioned(定位) 128

9.9 整理项目 12810 章 表单元素 129

10.1 准备 129

10.1.1 任务:准备项目(input) 129

10.1.2 任务:准备练习小部件PlaygroundInput 129

10.2 ElevatedButton(按钮) 130

10.3 TextField(文本字段) 133

10.3.1 任务:使用文本字段小部件 133

10.3.2 任务:获取文本字段里的数据 135

10.4 TextFormField(文本表单字段) 137

10.4.1 任务:使用文本表单字段 137

10.4.2 任务:验证文本表单字段数据 138

10.5 TextEditingController(文本编辑控制器) 141

10.6 Form(表单) 143

10.7 问题与思考 144

10.8 整理项目 14411章 路由导航(一) 145

11.1 准备 145

11.1.1 任务:准备项目(routing) 145

11.1.2 任务:准备导航与路由演示小部件 145

11.2 路由与导航器 146

11.3 用命令式管理路由 146

11.4 默认路由 149

11.5 路由表 151

11.6 生成路由时的回调 152

11.6.1 任务:使用生成路由回调onGenerateRoute 152

11.6.2 任务:在路由名字中提取参数 154

11.7 问题与思考 157

11.8 整理项目 15712章 状态管理 158

12.1 准备 158

12.1.1 任务:准备项目(state-management) 158

12.1.2 任务:准备状态管理演示小部件 158

12.1.3 任务:安装provider 159

12.2 准备数据 160

12.3 提供数据 161

12.3.1 确定提供数据的位置 162

12.3.2 任务:用Provider 提供数据与方法 162

12.4 使用数据 163

12.5 数据变化 165

12.5.1 任务:用ChangeNotifierProvider提供数据与方法 165

12.5.2 任务:在小部件里使用Provider 提供的数据与方法(Consumer) 167

12.6 问题与思考 168

12.7 整理项目 16813章 路由导航(二) 169

13.1 准备项目(routing_2) 169

13.2 页面 169

13.2.1 任务:使用Navigator 声明式接口(Pages API169

13.2.2 任务:使用MultiProvider 提供多个数据类 171

13.2.3 任务:动态添加与移除页面 173

13.3 路由器 176

13.3.1 任务:创建路由器代表(RouterDelegate) 176

13.3.2 任务:使用路由器管理路由(Router) 177

13.3.3 任务:应用状态变化时通知Router 重建Navigator 180

13.4 路由配置 181

13.4.1 调试Web 应用 181

13.4.2 任务:定义路由配置类型 181

13.4.3 任务:把路由信息转换成自定义的路由配置(parseRouteInformation) 182

13.4.4 任务:根据路由配置数据修改应用状态(setNewRoutePath) 184

13.4.5 任务:把路由配置转换成路由信息(restoreRoute Information) 185

13.5 问题与思考 188

13.6 整理项目 18814章 网络请求 189

14.1 准备 189

14.1.1 任务:准备项目(http) 189

14.1.2 任务:准备网络请求演示小部件 189

14.2 http 190

14.2.1 任务:安装http 并使用资源 190

14.2.2 任务:请求服务端接口获取数据 191

14.2.3 任务:将JSON 数据转换成自定义类型 193

14.2.4 任务:请求服务端接口创建内容(用户) 195

14.2.5 任务:发送用户登录请求 197

14.2.6 任务:请求服务端接口更新内容(用户) 200

14.3 序列化 202

14.4 问题与思考 205

14.5 整理项目 205

第三部分 Flutter实践

第15章 内容列表 208

15.1 准备项目(list) 208

15.2 应用配置 208

15.3 创建内容列表 210

15.3.1 任务:创建内容列表小部件(PostList) 210

15.3.2 任务:定义并提供获取内容列表数据方法 211

15.3.3 任务:请求内容列表数据 213

15.3.4 任务:定义内容数据类型 214

15.3.5 任务:转换生成一组内容(Post)类型的数据 217

15.3.6 任务:使用ListView 构建内容列表视图 220

15.4 整理项目 22116章 列表项目 222

16.1 准备项目(list-item) 222

16.2 定义列表项目 222

16.2.1 任务:创建内容列表项目小部件(PostListItem) 222

16.2.2 任务:定义内容媒体小部件(PostMedia) 224

16.2.3 任务:定义内容头部小部件(PostHeader) 226

16.2.4 任务:定义用户头像小部件(UserAvatar) 228

16.2.5 任务:定义内容动作小部件(PostActions) 230

16.3 问题与思考 233

16.4 整理项目 23417章 内容页面 235

17.1 准备项目(post) 235

17.2 开发单个内容页面 235

17.2.1 任务:处理单击内容列表项目图像 235

17.2.2 任务:定义单个内容数据模型(PostShowModel) 237

17.2.3 任务:单击内容项目图像时显示内容页面 240

17.2.4 任务:定义内容页面主体小部件(PageShowMain) 243

17.2.5 任务:定义内容正文小部件(PostContent) 247

17.2.6 任务:定义内容标签小部件(PostTags) 249

17.2.7 任务:配置路由器处理内容页面 251

17.2.8 任务:请求内容页面需要的数据 254

17.3 问题与思考 256

17.4 整理项目 25918章 验证身份 260

18.1 准备项目(auth) 260

18.2 登录页面 260

18.2.1 任务:添加用户登录页面 260

18.2.2 任务:准备登录表单小部件(AuthLoginForm) 263

18.3 请求登录 270

18.3.1 任务:定义用户登录相关类型(LoginData,Auth) 270

18.3.2 任务:自定义网络请求异常(HttpException) 271

18.3.3 任务:定义身份验证模型(AuthModel) 272

18.3.4 任务:请求用户登录 274

18.4 问题与思考 276

18.5 整理项目 27619章 状态管理 277

19.1 准备项目(state-management_2) 277

19.2 改造创建Provider 的方式 277

19.2.1 任务:使用Provider 的value 构造方法提供值 277

19.2.2 任务:在单独的文件里定义要提供的Provider 278

19.3 在用户设备上存取数据 279

19.3.1 任务:用shared preferences 插件记住登录状态 279

19.3.2 任务:应用启动以后恢复登录状态 282

19.4 使用代理Provider 解决依赖 285

19.4.1 任务:定义应用服务与接口客户端(AppService 和ApiHttpClient) 285

19.4.2 任务:用ChangeNotifierProxyProvider解决依赖 287

19.4.3 任务:改造PostIndexModel 用apiHttpClient 发送请求 288

19.5 整理项目 28920章 点赞内容 290

20.1 准备项目(like) 290

20.2 点赞内容相关操作 290

20.2.1 任务:使用GestureDetector 处理手势动作 290

20.2.2 任务:定义点赞内容模型 291

20.2.3 任务:定义取消点赞模型 292

20.2.4 任务:定义提供点赞的Provider 293

20.2.5 任务:处理用户点赞动作 294

20.2.6 任务:处理用户取消点赞动作 296

20.3 问题与思考 298

20.4 整理项目 29821章 列表布局 299

21.1 准备项目(post-list-layout) 299

21.2 内容列表布局 299

21.2.1 任务:准备热门内容列表 299

21.2.2 任务:准备内容列表布局相关数据与方法 301

21.2.3 任务:设置与存储内容列表布局 302

21.2.4 任务:准备网格内容列表 303

21.2.5 任务:准备多种布局的内容列表项目 305

21.2.6 任务:恢复内容列表布局 308

21.3 问题与思考 310

21.4 整理项目 312

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1196048.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Unity细节】Failed importing package???Unity导包失败?

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…

计算机服务器中了mallox勒索病毒怎么解决,勒索病毒解密,数据恢复

企业的计算机服务器为企业的数据存储提供了极大便利&#xff0c;也让企业的生产运行效率得到了极大提升&#xff0c;但是网络数据安全威胁随着技术的不断发展也不断增加。近期&#xff0c;云天数据恢复中心接到很多企业的求助&#xff0c;企业的计算机服务器遭到了mallox勒索病…

图神经网络 (GNN)

目录 一、GNN介绍1.1引入1.1.1图的介绍1.1.2怎样将内容表示成图1.1.4图神经网络是在做什么 1.2基本概念 二、GNN流程2.1聚合2.2更新2.2.1一次GNN操作 2.3循环2.3.1多层GNN操作2.3.2能做什么 三、GNN算法原理3.1数据3.2变量定义3.3GNN算法3.3.1Forward3.3.2Backward 四、GNN优势…

Unity 调用自己封装好的DLL库

因为做项目时会用到很多重复的方法&#xff0c;每次都重新写有点浪费时间&#xff0c;就可以将这些方法封装成DLL类库&#xff0c;用的时候直接引入调用就行。 首先在VS里面创建类库文件 注&#xff1a;.NET Framework要选3.5以下 然后定义好命名空间名字和类名就可以写自己要…

互联网按摩预约小程序开发;

随着移动互联网的普及&#xff0c;越来越多的人开始通过手机预约按摩服务。按摩预约小程序是一种方便快捷的预约方式&#xff0c;可以让用户随时随地预约按摩服务。那么&#xff0c;按摩预约小程序的开发周期要多久&#xff1f;按摩预约小程序的功能有哪些呢&#xff1f;本文将…

振南技术干货集:研发版本乱到“妈不认”? Git!(1)

注解目录 1、关于 Git 1.1Git 今生 (Git 和 Linux 的生父都是 Linus&#xff0c;振南给你讲讲当初关于 Git 的爱恨情愁&#xff0c;其背后其实是开源与闭源两左阵营的明争暗斗。) 1.2Git的爆发 (Git 超越时代的分布式思想。振南再给你讲讲旧金山三个年轻人创办 GitHub&…

ABAQUS分析步笔记

定义原则&#xff1a; 每个step的所有边界条件&#xff0c;载荷条件累加构成本step的仿真效果&#xff1b; step2需要在step1的状态基础上进行载荷运动等限定时&#xff0c;需要确保在step2中传递了step1的想要保留的特征&#xff0c;如&#xff1a; 1、BC-1 这里的BC-1的固…

2024最新fl studio 21.2.0.3842中文版完整下载

FL Studio 21.2.0.3842中文版完整下载是最好的音乐开发和制作软件也称为水果音乐软件。它是最受欢迎的工作室&#xff0c;因为它包含了一个主要的听觉工作场所。2024最新fl studioFL Studio 21版有不同的功能&#xff0c;如它包含图形和音乐音序器&#xff0c;帮助您使完美的配…

JRebel热部署——效率提升100倍(程序员工具必备)

1. 下载JRebel 2.激活程序 这里推荐一个免费获取jrebel激活服务器地址和激活邮箱的地址:点击进入 进入网站之后就可以获取到激活链接和邮箱 点击进入激活 复制过去激活就可以 然后就可以看到激活成功了 3.如何使用 代码修改后&#xff0c;直接CtrlShitF9 即可重新启动 4…

阿里云服务器怎么样?阿里云服务器优势、价格及常见问题介绍

阿里云&#xff08;Alibaba Cloud&#xff09;是阿里巴巴集团旗下的云计算服务提供商&#xff0c;其提供的云服务器&#xff08;ECS&#xff09;是其核心服务之一。在云计算市场中&#xff0c;阿里云服务器备受用户的青睐&#xff0c;那么&#xff0c;阿里云服务器究竟怎么样呢…

基于SSM的房屋租售信息管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

“基于RflySim平台飞控底层算法开发”系列专题培训 (第三期)

>> RflySim平台系列专题培训 RflySim平台是一个生态系统或工具链&#xff08;官网&#xff1a;https://doc.rflysim.com&#xff09;&#xff0c;发起于北航可靠飞行控制研究组&#xff0c;主要用于遵循基于模型设计的思想进行无人系统的控制和安全测试。本平台选择MATL…

合成数据加速机器视觉学习

虽然机器学习在基于视觉的自动化中的应用正在增长&#xff0c;但许多行业都面临着挑战&#xff0c;并难以在其计算机视觉应用中实施它。这在很大程度上是由于需要收集许多图像&#xff0c;以及与准确注释这些图像中的不同产品相关的挑战。 该领域的最新趋势之一是利用合成数据…

51单片机PCF8591数字电压表数码管显示设计( proteus仿真+程序+设计报告+讲解视频)

PCF8591数字电压表数码管显示 1.主要功能&#xff1a;讲解视频&#xff1a;2.仿真3. 程序代码4. 设计报告5. 设计资料内容清单&&下载链接资料下载链接&#xff08;可点击&#xff09;&#xff1a; 51单片机PCF8591数字电压表数码管设计( proteus仿真程序设计报告讲解视…

C++以数组作为参数,传递数组地址

文章目录 函数如何使用指针来处理数组将数组作为参数意味着什么数组名和指针对应是好的吗&#xff1f; 参考资料 函数如何使用指针来处理数组 在大多数情况下&#xff0c;C和 C 语言一样&#xff0c;也将数组名视为指针。 C将数组名解释为其第一个元素的地址: cookies &…

YOLOv8 Ultralytics:使用Ultralytics框架训练RT-DETR实时目标检测模型

YOLOv8 Ultralytics&#xff1a;使用Ultralytics框架训练RT-DETR实时目标检测模型 前言相关介绍前提条件实验环境安装环境项目地址LinuxWindows 制作自己的数据集训练自己的数据集创建自己数据集的yaml文件football.yaml文件内容 进行训练进行验证进行预测 数据集获取参考文献 …

NAS 扩容简明指南:使用各种外设给 NAS 们扩容

说起来有趣&#xff0c;NAS 除了“不同设备共享存储”这个功能之外&#xff0c;最重要的功能就是为设备扩容&#xff0c;但是 NAS 自己的存储容量不够了&#xff0c;又该如何。 ​这篇文章分享下我目前使用外设给 NAS 扩容的思路&#xff0c;如何以相对低的成本来获取更大的容…

IPV6网络技术详细介绍

无状态和有状态并不是相互对立的&#xff0c;他们可以同时存在&#xff0c;也就是一张网卡上可以同时出现通过RA生成的IP以及通过DHCPv6获得的IP。 从图中可以看到&#xff0c;顺序为&#xff1a; 1、Stateless自动配置“链路本地地址”2、Stateless自动配置“全球地址”&…

mysql基础 --子查询

文章目录 子查询 子查询 一个查询语句&#xff0c;嵌套在另一个查询语句内部&#xff1b;子查询先执行&#xff0c;其结果被外层主查询使用&#xff1b;子查询放入括号内&#xff1b;子查询放在比较条件的右侧&#xff1b;子查询返回一条&#xff0c;为单行子查询&#xff1b;…

普华永道于进博会首发“企业数据资源会计处理一体化平台”

11月6日&#xff0c;在第六届中国国际进口博览会上&#xff0c;普华永道发布企业数据资源会计处理一体化平台&#xff08;英文名为Data Accounting Platform&#xff0c;简称DAP&#xff09;。该产品以普华永道“五步法”数据资源入表路径为理论依据&#xff0c;依托多年来普华…