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

在这里插入图片描述

前言

还记得你学习 Flutter 的第一个官方教程 “Write your first Flutter app” 吗?
那个无限滚动的列表,每次滑动都会生成新的单词组合,点击心形图标即可收藏。
这一切的背后,都依赖于一个极其小巧但功能强大的库 —— english_words

它包含了最常用的 2534 个英语单词(名词、形容词、动词等),并提供了一套算法来随机生成看起来“像样”的词组(如 StartupNamer)。
对于 OpenHarmony 开发者,它不仅仅是一个 Demo 工具,更是构建创意命名、随机昵称、验证码生成等功能的利器。

一、核心原理与数据结构

1.1 词库来源与优化

english_words 的数据并未直接存储为巨大的 JSON 文件,而是硬编码在 Dart 源码中(作为 List<String> 常量)。
这样做的好处是:

  • 零 IO:无需解析 JSON,应用启动即加载。
  • Tree Shaking:如果你只用了 adjectives,Dart 编译器会自动剔除未使用的 nouns,减小包体积。
  • 性能极高:直接内存访问。

1.2 组合生成算法 (WordPair)

核心类 WordPair 代表两个单词的组合(如 bluesky -> BlueSky)。
它并不只是简单的字符串拼接,而是经过了精心挑选。

  • PascalCase: BlueSky
  • camelCase: blueSky
  • snake_case: blue_sky
  • lower case: bluesky

库内部使用了高效的随机索引算法,确保生成的组合既具备随机性,又避免了一些生僻词组合。

调用 generateWordPairs

随机索引

随机索引

选取

选取

组合

Flutter 应用

english_words 库

常用名词库

常用形容词库

名词 (如 Blue)

形容词 (如 Sky)

WordPair(Blue, Sky)

二、核心 API 详解

2.1 生成单词组合

import 'package:english_words/english_words.dart';

void main() {
  // 1. 生成 10 个随机组合
  generateWordPairs().take(10).forEach((pair) {
    print(pair.asPascalCase); // RedBicycle, ShinyApple...
  });

  // 2. 将组合转为不同格式
  final pair = WordPair("super", "hero");
  print(pair.asCamelCase); // superHero
  print(pair.asSnakeCase); // super_hero
  print(pair.asLowerCase); // superhero
  print(pair.asUpperCase); // SUPERHERO
}

在这里插入图片描述

2.2 直接访问词库

有时我们需要单个名词或形容词。

// 获取所有名词 (约 2500 个)
print(nouns.take(5));

// 获取所有形容词 (约 1200 个)
print(adjectives.take(5));

// 检查是否包含某个单词
print(all.contains('flutter')); // true

在这里插入图片描述

2.3 音节与押韵 (Syllables & Rhymes)

这是库的高级功能。它不仅限于字符串,还包含简单的语音规则。

// 计算音节数
print(syllables('hello')); // 2 (hel-lo)
print(syllables('beautiful')); // 3 (beau-ti-ful)

// 简单的押韵检测 (Demo 级)
bool rhyme(String word1, String word2) {
  // ... 基于后缀匹配 ...
}

三、OpenHarmony 平台适配实战

3.1 实战:构建鸿蒙版 Startup Namer

我们将经典 Flutter Demo 移植到鸿蒙,并增加持久化功能。

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
// 需配合 shared_preferences 适配
import 'package:shared_preferences/shared_preferences.dart'; 

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Ohos Name Generator',
      home: RandomWords(),
    );
  }
}

class RandomWords extends StatefulWidget {
  
  _RandomWordsState createState() => _RandomWordsState();
}

class _RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _saved = <WordPair>{};
  
  
  void initState() {
    super.initState();
    _loadSaved();
  }

  // 从本地存储加载收藏
  Future<void> _loadSaved() async {
    final prefs = await SharedPreferences.getInstance();
    final List<String> savedStrings = prefs.getStringList('saved_names') ?? [];
    setState(() {
      _saved.addAll(savedStrings.map((s) {
        var parts = s.split(/(?=[A-Z])/); // 简单拆分 PascalCase
        return WordPair(parts[0].toLowerCase(), parts[1].toLowerCase());
      }));
    });
  }

  void _pushSaved() {
    Navigator.of(context).push(
      MaterialPageRoute<void>(
        builder: (BuildContext context) {
          final tiles = _saved.map(
            (WordPair pair) {
              return ListTile(
                title: Text(
                  pair.asPascalCase,
                  style: TextStyle(fontSize: 18.0),
                ),
              );
            },
          );
          final divided = ListTile.divideTiles(
            context: context,
            tiles: tiles,
          ).toList();

          return Scaffold(
            appBar: AppBar(title: Text('Saved Suggestions')),
            body: ListView(children: divided),
          );
        },
      ),
    );
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
        actions: [
          IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
        ],
      ),
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions() {
    return ListView.builder(
      padding: EdgeInsets.all(16.0),
      itemBuilder: (context, i) {
        if (i.isOdd) return Divider();

        final index = i ~/ 2;
        if (index >= _suggestions.length) {
          _suggestions.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_suggestions[index]);
      },
    );
  }

  Widget _buildRow(WordPair pair) {
    final alreadySaved = _saved.contains(pair);
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: TextStyle(fontSize: 18.0),
      ),
      trailing: Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
        // 实时保存
        SharedPreferences.getInstance().then((prefs) {
          prefs.setStringList(
            'saved_names', 
            _saved.map((p) => p.asPascalCase).toList()
          );
        });
      },
    );
  }
}

在这里插入图片描述

3.2 进阶:随机昵称生成器

在社交 App 中,用户不想填昵称时,我们可以给一个默认值。

  void _generate() {
    // 💡 组合策略:形容词 + 名词 + 随机两位数
    // 注意:adjectives 和 nouns 是不可变列表,需要先复制为可变列表再 shuffle
    final adjList = List<String>.from(adjectives)..shuffle();
    final nounList = List<String>.from(nouns)..shuffle();

    final adj = adjList.first;
    final noun = nounList.first;
    final suffix = Random().nextInt(99).toString().padLeft(2, '0');

    setState(() {
      _nickname = '${adj.capitalize()}${noun.capitalize()}$suffix';
    });
  }

在这里插入图片描述

四、性能与包体积考量

4.1 包体积 (Size)

english_words 包含约 4000 个单词。如果不 Treeshake,可能会增加约 50KB 的包体积。这在现代 App 中完全可以忽略不计。
但如果你正在构建极简的 Instant App(原子服务),可以考虑只 fork 下来这部分代码,手动删减不用的单词。

4.2 启动时间

由于是 const List,加载速度极快,不会阻塞 UI 线程。在鸿蒙设备上测试,从 main() 到第一帧渲染完全无感知。

五、总结

english_words 让我们见识到了 Dart 语言处理基础数据的优雅。它没有复杂的逻辑,却通过简单的组合产生了无限的创意。

对于 OpenHarmony 开发者:

  1. 教学工具:它是演示 ListView, State, Navigation 最好的例子。
  2. 创意工具:不仅是 Startup Namer,任何需要随机文本的地方(测试数据、占位符、默认昵称),它都是首选。

Logo

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

更多推荐