Flutter 诗词大会应用的鸿蒙化开发实战

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

作者:maaath

一、引言

随着国产操作系统生态的蓬勃发展,OpenHarmony 作为一款面向全场景的分布式操作系统,正吸引着越来越多的开发者加入。Flutter 作为 Google 开源的跨平台 UI 框架,凭借其高性能、丰富的组件库和活跃的社区生态,已成为移动端开发的主流选择之一。而 Flutter for OpenHarmony 的出现,让开发者能够将已有的 Flutter 应用快速迁移到鸿蒙设备上,实现一次编写、多端运行。

本文将带领读者从零开始,使用 Flutter 构建一款功能完整的"诗词大会"应用,并成功运行在 OpenHarmony 设备上。通过本文的实践,读者将掌握 Flutter 在鸿蒙平台上的开发流程、数据管理、页面路由等核心技能。

二、项目概述

"诗词大会"是一款面向诗词爱好者的综合性学习与娱乐应用,包含以下 8 大核心功能模块:

功能模块 说明
诗词背诵挑战 随机抽取诗词,填空式背诵,即时判分
飞花令对战 双人轮流说出含指定关键字的诗句
诗句接龙 首尾字相接,AI 辅助提示
诗词闯关游戏 5 关递进式选择题挑战
诗词作者介绍 8 位著名诗人的生平与作品
诗词收藏背诵 收藏喜爱的诗词,支持默写检测
每日诗词推荐 每日一首精选诗词配赏析
诗词水平测试 10 道随机题目,5 级评级体系

整个项目基于 Flutter 框架开发,使用 Dart 语言编写,通过 Flutter for OpenHarmony 的适配层,无需修改任何平台代码即可在鸿蒙设备上运行。

三、项目架构设计

3.1 整体架构

项目采用经典的分层架构,分为数据模型层、服务层和页面展示层:

lib/
├── main.dart                    # 应用入口
├── models/
│   └── poetry_model.dart        # 数据模型定义
├── services/
│   └── poetry_service.dart      # 业务逻辑与数据管理
└── pages/
    ├── home_page.dart           # 主页面入口
    └── poetry/
        ├── poetry_home_page.dart      # 诗词大会首页
        ├── recite_challenge_page.dart # 背诵挑战
        ├── feihualing_page.dart       # 飞花令对战
        ├── poetry_chain_page.dart     # 诗句接龙
        ├── challenge_game_page.dart   # 闯关游戏
        ├── author_intro_page.dart     # 作者介绍
        ├── collection_page.dart       # 收藏背诵
        ├── daily_recommend_page.dart  # 每日推荐
        └── level_test_page.dart       # 水平测试

3.2 数据模型设计

数据模型是整个应用的基石。我们使用 Dart 的类来定义诗词、作者、游戏状态等核心数据结构。以下是 Poetry 模型的定义:

class Poetry {
  final String id;
  final String title;
  final String author;
  final String dynasty;
  final String content;
  final List<String> lines;
  final String category;
  final String description;
  bool isFavorite;

  Poetry({
    required this.id,
    required this.title,
    required this.author,
    required this.dynasty,
    required this.content,
    required this.lines,
    required this.category,
    required this.description,
    this.isFavorite = false,
  });

  String get firstChar => lines.isNotEmpty ? lines.first[0] : '';
  String get lastChar => lines.isNotEmpty ? lines.last[lines.last.length - 1] : '';
}

这里的关键设计点是 lines 字段将诗词按行拆分,便于后续的填空背诵、接龙等功能的实现。firstCharlastChar 两个 getter 方法用于诗句接龙功能中获取首尾字。

3.3 服务层设计

服务层采用单例模式,集中管理所有诗词数据和游戏逻辑。核心代码如下:

class PoetryService {
  static final PoetryService _instance = PoetryService._();
  factory PoetryService() => _instance;
  PoetryService._();

  final List<Poetry> _poems = [];
  final List<PoetryAuthor> _authors = [];
  final List<ChallengeLevel> _levels = [];
  final Random _random = Random();

  // 获取每日推荐诗词
  Poetry getDailyPoem() {
    _initData();
    final today = DateTime.now();
    final dateKey = DateTime(today.year, today.month, today.day);

    if (_dailyPoem != null && _dailyPoemDate == dateKey) {
      return _dailyPoem!;
    }

    _dailyPoemDate = dateKey;
    _dailyPoem = _poems[_random.nextInt(_poems.length)];
    return _dailyPoem!;
  }

  // 生成背诵挑战
  ReciteChallenge generateReciteChallenge() {
    _initData();
    final poem = _poems[_random.nextInt(_poems.length)];
    final lineCount = poem.lines.length;
    final blankCount = min(3, lineCount);
    final blankPositions = <int>[];
    final correctAnswers = <String>[];

    final indices = List.generate(lineCount, (i) => i)..shuffle(_random);
    for (var i = 0; i < blankCount; i++) {
      blankPositions.add(indices[i]);
      correctAnswers.add(poem.lines[indices[i]]);
    }
    blankPositions.sort();

    return ReciteChallenge(
      poetry: poem,
      blankPositions: blankPositions,
      correctAnswers: correctAnswers,
    );
  }

  // 搜索诗词
  List<Poetry> searchPoems(String query) {
    _initData();
    if (query.isEmpty) return allPoems;
    return _poems.where((p) =>
        p.title.contains(query) ||
        p.author.contains(query) ||
        p.content.contains(query) ||
        p.lines.any((line) => line.contains(query))
    ).toList();
  }
}

服务层封装了数据初始化、随机抽取、搜索过滤等核心逻辑,页面层只需调用相应方法即可获取数据,实现了关注点分离。

四、核心功能实现

4.1 诗词背诵挑战

背诵挑战功能随机选取一首诗词,将其中的若干行挖空,用户需要在空白处填入正确的诗句。实现思路如下:

Widget _buildBlankLine(int index) {
  final blankIndex = _challenge.blankPositions.indexOf(index);
  final correctAnswer = _challenge.correctAnswers[blankIndex];

  return Padding(
    padding: const EdgeInsets.symmetric(vertical: 6),
    child: _submitted
        ? _buildSubmittedBlank(index, blankIndex, correctAnswer)
        : TextFormField(
            controller: _controllers[index],
            textAlign: TextAlign.center,
            style: const TextStyle(
              fontSize: 18,
              color: Color(0xFF8B4513),
              fontFamily: 'serif',
            ),
            decoration: InputDecoration(
              hintText: '请输入第${blankIndex + 1}句',
              filled: true,
              fillColor: Color(0xFFFFF8DC),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: BorderSide(color: Color(0xFFDEB887)),
              ),
            ),
            validator: (value) {
              if (value == null || value.trim().isEmpty) {
                return '请填写诗句';
              }
              return null;
            },
          ),
  );
}

提交后系统会逐句比对,显示对错并给出正确答案,同时累计得分。这种即时反馈机制能有效提升学习效果。

4.2 飞花令对战

飞花令是传统诗词游戏,两人轮流说出含有指定关键字的诗句。我们实现了双人对战模式,并提供了 AI 代答功能:

void _submitAnswer() {
  final answer = _answerController.text.trim();
  if (answer.isEmpty) {
    setState(() => _message = '请输入诗句');
    return;
  }

  if (!_poetryService.validateFeihualingAnswer(_game!, answer)) {
    setState(() => _message = '未找到含有"${_game!.keyword}"的诗句,或已被使用');
    return;
  }

  setState(() {
    if (_game!.currentPlayer == 1) {
      _game!.player1Answers = [..._game!.player1Answers, answer];
      _game!.player1Score++;
      _game!.currentPlayer = 2;
      _message = '玩家1得分!轮到玩家2';
    } else {
      _game!.player2Answers = [..._game!.player2Answers, answer];
      _game!.player2Score++;
      _game!.currentPlayer = 1;
      _message = '玩家2得分!轮到玩家1';
    }
    _answerController.clear();
  });
}

AI 代答功能会从诗词库中检索未被使用过的、包含关键字的诗句,让单人也能畅玩飞花令。

4.3 诗词闯关游戏

闯关游戏设计了 5 个递进式关卡,每关 5 道选择题,涵盖诗词背诵、作者知识、文学常识等。关卡解锁机制增加了游戏的挑战性:

void _finishLevel() {
  final level = _levels[_currentLevelIndex!];
  final totalQuestions = level.questions.length;
  final score = (_correctCount / totalQuestions * 100).round();

  if (score >= level.requiredScore) {
    level.isCompleted = true;
    level.bestScore = score > level.bestScore ? score : level.bestScore;
    if (_currentLevelIndex! + 1 < _levels.length) {
      _levels[_currentLevelIndex! + 1].isUnlocked = true;
    }
  }
  // 弹出结果对话框
}

4.4 每日诗词推荐

每日推荐功能根据当前日期缓存一首诗词,确保用户每天打开应用都能看到不同的推荐内容:

Poetry getDailyPoem() {
  _initData();
  final today = DateTime.now();
  final dateKey = DateTime(today.year, today.month, today.day);

  if (_dailyPoem != null && _dailyPoemDate == dateKey) {
    return _dailyPoem!;
  }

  _dailyPoemDate = dateKey;
  _dailyPoem = _poems[_random.nextInt(_poems.length)];
  return _dailyPoem!;
}

五、Flutter for OpenHarmony 适配要点

5.1 项目配置

在将 Flutter 项目迁移到 OpenHarmony 时,需要确保 pubspec.yaml 中不包含鸿蒙不支持的第三方依赖。本项目仅使用了 Flutter 官方 SDK 和 cupertino_icons,无需额外适配:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8

5.2 构建与运行

在鸿蒙设备上运行 Flutter 应用,需要先配置好 Flutter for OpenHarmony 的开发环境。构建命令与标准 Flutter 项目一致:

# 调试模式构建
flutter build ohos --debug

# 运行到鸿蒙设备
flutter run --device-ohos

5.3 兼容性注意事项

在开发过程中,有几个关键的兼容性要点需要留意:

  1. 图标使用:部分 Material Icons 在鸿蒙平台上可能不可用,建议使用基础图标集。例如 Icons.swords 不可用,应替换为 Icons.shield

  2. 字符串操作:Dart 的 characters API 在部分 Flutter for OpenHarmony 版本中可能不支持,建议使用下标索引 [0][length - 1] 替代。

  3. 列表可变性:在模型类中,如果需要在运行时修改列表内容,不要使用 final 修饰,应声明为可变列表。

六、运行效果展示

以下是在鸿蒙设备上运行"诗词大会"应用的截图:

6.1 诗词大会首页

首页展示了每日推荐诗词和 8 大功能入口,采用中国传统色调(棕色、米色)营造古典氛围。顶部渐变背景搭配"赏中华诗词,寻文化基因,品生活之美"的标语,突出文化主题。
在这里插入图片描述

6.2 背诵挑战界面

背诵挑战页面随机选取诗词,将部分诗句挖空。用户填写后提交,系统会逐句比对并显示对错。答对全部题目可获得满分评价。
在这里插入图片描述
在这里插入图片描述

6.3 飞花令对战界面

飞花令对战页面支持双人轮流作答,实时显示比分。用户可选择"花、月、风、春"等 15 个关键字,AI 代答功能让单人也能畅玩。
在这里插入图片描述
在这里插入图片描述

6.4 闯关游戏界面

闯关游戏包含 5 个递进式关卡,每关 5 道选择题。答对一定比例即可解锁下一关,并记录最高分。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.5 水平测试结果

水平测试完成后,系统根据正确率给出 5 级评级(诗词新秀→诗词大师),并显示详细得分和评语。
在这里插入图片描述
在这里插入图片描述

:以上截图均来自鸿蒙真机运行效果,验证了 Flutter for OpenHarmony 的完整兼容性。

七、总结与展望

本文详细介绍了使用 Flutter 构建"诗词大会"应用并在 OpenHarmony 平台上运行的全过程。通过 8 大功能模块的实现,展示了 Flutter 在鸿蒙生态中的强大能力。

Flutter for OpenHarmony 为开发者提供了一条低成本的跨平台开发路径。对于已有 Flutter 经验开发者来说,迁移成本极低;对于新入门的开发者,Flutter 丰富的组件库和完善的工具链也能大幅提升开发效率。

未来,我们可以进一步扩展应用功能,例如接入在线诗词数据库、实现用户对战匹配、添加语音朗诵识别等。随着 OpenHarmony 生态的不断完善,Flutter 在鸿蒙平台上的表现也将越来越出色。

八、获取源码

欢迎访问 AtomGit(https://atomgit.com)获取完整源码,也欢迎加入开源鸿蒙跨平台社区(https://openharmonycrossplatform.csdn.net)交流讨论,共同推动 Flutter for OpenHarmony 生态发展。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐