🚀运行效果展示

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Flutter框架跨平台鸿蒙开发——火车票查询APP的开发流程

前言

随着移动互联网的快速发展,铁路出行已成为人们日常生活中不可或缺的交通方式。火车票查询作为出行的第一步,其移动应用的便捷性和用户体验显得尤为重要。传统的原生开发需要分别为Android和iOS维护两套代码,开发成本高、周期长。而Flutter框架的出现彻底改变了这一局面,它提供了一套代码同时构建多平台应用的解决方案。

本项目基于Flutter框架开发火车票查询APP,充分利用Flutter的跨平台特性和HarmonyOS(鸿蒙系统)的分布式能力,实现了从查询到预订的完整用户体验流程。通过本项目,我们深入探索了Flutter在鸿蒙生态中的开发实践,为后续更多跨平台应用的开发积累了宝贵经验。

🚂 火车票查询APP,让您的出行更加便捷!

应用介绍

应用背景

火车票查询APP是一款面向广大铁路出行用户的移动端应用,旨在为用户提供快速、准确、便捷的火车票查询服务。在数字化转型的浪潮下,传统的人工查询方式已无法满足现代用户的需求,用户期望能够随时随地通过手机查询车次信息、票价、余票等信息。

核心功能

本应用主要包含以下核心功能模块:

功能模块 功能描述 技术实现
车站查询 支持按名称、拼音、代码搜索车站 模糊匹配算法
车次查询 按出发站、到达站、日期查询车次 条件筛选引擎
票价计算 根据距离和座位类型计算票价 费率模型计算
余票查询 实时显示各座位类型余票数量 数据可视化
历史记录 保存用户最近的搜索记录 本地存储

技术特点

本项目采用Flutter作为主要开发框架,充分利用了其以下技术优势:

  • 跨平台能力:一套代码同时支持Android、iOS、HarmonyOS等多个平台
  • 高性能渲染:采用Skia图形引擎,提供60fps的流畅动画效果
  • 响应式架构:基于Widget的组件化设计,便于维护和扩展
  • 热重载支持:开发阶段快速迭代,提升开发效率

系统架构设计

整体架构

本应用采用分层架构设计,从上到下依次为:表现层、业务逻辑层、数据层。这种分层设计使得各层职责清晰,便于代码的维护和测试。

Data Layer

Business Logic Layer

Presentation Layer

Flutter Widgets

Screens

Custom Widgets

Services

Models

State Management

Local Storage

API Service

Cache Manager

文件目录结构

项目采用标准的Flutter目录结构,将不同职责的代码放在对应的目录中:

lib/
├── main.dart                 # 应用入口
├── main_train_ticket.dart    # 火车票应用入口
├── models/                   # 数据模型
│   └── train_ticket_model.dart
├── screens/                  # 页面组件
│   └── train_ticket_query_screen.dart
├── services/                 # 业务服务
│   └── train_ticket_service.dart
└── widgets/                  # 通用组件

数据流设计

应用采用自上而下的数据流设计,页面组件负责UI渲染,服务层负责业务逻辑,数据层负责数据持久化和网络请求。这种单向数据流的设计使得数据流向清晰,便于调试和问题定位。

数据层 业务服务 页面组件 用户 数据层 业务服务 页面组件 用户 输入查询条件 调用查询方法 请求数据 返回数据 返回结果 展示查询结果

核心功能实现

1. 数据模型设计

数据模型是整个应用的基础,它定义了应用中各种数据的结构和关系。本项目定义了三个核心数据模型:TrainTicket(火车票)、SeatInfo(座位信息)和Station(车站信息)。

/// 火车票数据模型
/// 包含车次、座位、票价等信息
class TrainTicket {
  /// 车次编号
  final String trainNumber;
  
  /// 出发站
  final String departureStation;
  
  /// 到达站
  final String arrivalStation;
  
  /// 出发时间
  final String departureTime;
  
  /// 到达时间
  final String arrivalTime;
  
  /// 座位信息列表
  final List<SeatInfo> seats;

  /// 构造函数
  TrainTicket({
    required this.trainNumber,
    required this.departureStation,
    required this.arrivalStation,
    required this.departureTime,
    required this.arrivalTime,
    required this.seats,
  });

  /// 从JSON创建对象
  factory TrainTicket.fromJson(Map<String, dynamic> json) {
    return TrainTicket(
      trainNumber: json['trainNumber'] ?? '',
      departureStation: json['departureStation'] ?? '',
      arrivalStation: json['arrivalStation'] ?? '',
      departureTime: json['departureTime'] ?? '',
      arrivalTime: json['arrivalTime'] ?? '',
      seats: (json['seats'] as List<dynamic>?)
          ?.map((e) => SeatInfo.fromJson(e))
          .toList() ?? [],
    );
  }
}

/// 座位信息模型
class SeatInfo {
  /// 座位类型
  final String type;
  
  /// 价格
  final double price;
  
  /// 可用数量
  final int available;

  /// 构造函数
  SeatInfo({
    required this.type,
    required this.price,
    required this.available,
  });
}

2. 业务服务层

业务服务层负责处理核心业务逻辑,包括查询火车票、搜索车站、计算票价等功能。本项目中的TrainTicketService类封装了所有与火车票相关的业务逻辑。

/// 火车票查询服务类
/// 提供火车票查询、时刻表、票价等数据服务
class TrainTicketService {
  /// 模拟数据标记
  final bool _useMockData = true;

  /// 查询火车票
  /// 
  /// [fromStation] 出发站
  /// [toStation] 到达站
  /// [date] 出发日期
  /// [trainType] 车次类型筛选
  Future<List<TrainTicket>> queryTickets({
    required String fromStation,
    required String toStation,
    required DateTime date,
    String trainType = '全部',
  }) async {
    await Future.delayed(const Duration(milliseconds: 800));
    
    if (_useMockData) {
      return _generateMockTickets(fromStation, toStation, trainType);
    }
    
    return [];
  }

  /// 搜索车站
  /// 
  /// [keyword] 搜索关键词
  Future<List<Station>> searchStations(String keyword) async {
    final lowercaseKeyword = keyword.toLowerCase();
    return _commonStations
        .where((station) =>
            station.name.contains(keyword) ||
            station.pinyin.toLowerCase().contains(lowercaseKeyword) ||
            station.code.toLowerCase().contains(lowercaseKeyword))
        .toList();
  }

  /// 计算票价
  /// 
  /// [distance] 距离(公里)
  /// [seatType] 座位类型
  double calculatePrice(int distance, String seatType) {
    final baseRate = <String, double>{
      '商务座': 1.2,
      '一等座': 0.8,
      '二等座': 0.5,
      '软卧': 0.6,
      '硬卧': 0.4,
      '硬座': 0.3,
      '无座': 0.3,
    };

    final rate = baseRate[seatType] ?? 0.5;
    return distance * rate * 0.5;
  }
}

3. 页面组件实现

页面组件是用户与应用交互的入口,本项目中的TrainTicketQueryScreen组件实现了完整的查询界面和交互逻辑。

/// 火车票查询页面
/// 提供火车票查询、时刻表查看、票价计算等功能
class TrainTicketQueryScreen extends StatefulWidget {
  /// 构造函数
  const TrainTicketQueryScreen({super.key});

  
  State<TrainTicketQueryScreen> createState() => _TrainTicketQueryScreenState();
}

/// 火车票查询页面状态类
class _TrainTicketQueryScreenState extends State<TrainTicketQueryScreen> {
  final TextEditingController _fromStationController = TextEditingController();
  final TextEditingController _toStationController = TextEditingController();
  final TrainTicketService _trainTicketService = TrainTicketService();
  
  DateTime _selectedDate = DateTime.now();
  String _selectedTrainType = '全部';
  bool _isSearching = false;
  List<TrainTicket> _searchResults = [];

  /// 执行火车票查询
  Future<void> _searchTickets() async {
    final fromStation = _fromStationController.text.trim();
    final toStation = _toStationController.text.trim();

    if (fromStation.isEmpty) {
      _showSnackBar('请输入出发站');
      return;
    }

    if (toStation.isEmpty) {
      _showSnackBar('请输入到达站');
      return;
    }

    setState(() {
      _isSearching = true;
      _searchResults = [];
    });

    try {
      final results = await _trainTicketService.queryTickets(
        fromStation: fromStation,
        toStation: toStation,
        date: _selectedDate,
        trainType: _selectedTrainType,
      );

      setState(() {
        _searchResults = results;
      });
    } catch (e) {
      _showSnackBar('查询失败,请稍后重试');
    } finally {
      setState(() {
        _isSearching = false;
      });
    }
  }
}

4. 核心算法实现

4.1 模糊搜索算法

为了提供更好的用户体验,我们实现了支持拼音、汉字、车站代码多种搜索方式的模糊搜索算法:

/// 搜索车站
/// 支持按名称、拼音、代码搜索
Future<List<Station>> searchStations(String keyword) async {
  final lowercaseKeyword = keyword.toLowerCase();
  return _commonStations
      .where((station) =>
          station.name.contains(keyword) ||
          station.pinyin.toLowerCase().contains(lowercaseKeyword) ||
          station.code.toLowerCase().contains(lowercaseKeyword))
      .toList();
}
4.2 票价计算算法

票价计算采用基于距离和座位类型的费率模型:

/// 计算票价
/// 根据距离和座位类型计算票价
double calculatePrice(int distance, String seatType) {
  final baseRate = <String, double>{
    '商务座': 1.2,  // 商务座费率
    '一等座': 0.8,  // 一等座费率
    '二等座': 0.5,  // 二等座费率
    '软卧': 0.6,    // 软卧费率
    '硬卧': 0.4,    // 硬卧费率
    '硬座': 0.3,    // 硬座费率
    '无座': 0.3,    // 无座费率
  };

  final rate = baseRate[seatType] ?? 0.5;
  return distance * rate * 0.5;
}

界面设计

整体布局

应用界面采用响应式设计,适配不同屏幕尺寸。主要布局结构如下:

Scaffold

AppBar

Container背景

SafeArea

SingleChildScrollView

Column

搜索卡片

车次类型筛选

搜索按钮

查询结果

出发站输入

交换按钮

到达站输入

日期选择

界面组件

应用中的主要界面组件包括:

  1. 搜索卡片:包含出发站、到达站输入框和日期选择器
  2. 车次类型筛选器:提供多种车次类型的选择
  3. 火车票卡片:展示每趟列车的详细信息
  4. 座位信息标签:用不同颜色区分各种座位类型

响应式设计实现

为了适配不同尺寸的屏幕,应用采用了以下响应式设计策略:

/// 构建车次类型筛选
Widget _buildTrainTypeFilter() {
  return SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: Row(
      children: _trainTypes.map((type) {
        final isSelected = _selectedTrainType == type;
        return Padding(
          padding: const EdgeInsets.only(right: 8),
          child: FilterChip(
            selected: isSelected,
            label: Text(type),
            selectedColor: Colors.blue.shade100,
            checkmarkColor: Colors.blue,
            onSelected: (selected) {
              setState(() {
                _selectedTrainType = type;
              });
            },
          ),
        );
      }).toList(),
    ),
  );
}

视觉设计规范

应用的视觉设计遵循以下规范:

设计元素 规范 示例
主色调 蓝色系 Colors.blue
卡片圆角 16px BorderRadius.circular(16)
按钮圆角 12px BorderRadius.circular(12)
文字大小 标题18px,正文14px TextStyle(fontSize: 18)
间距 16px标准间距 EdgeInsets.all(16)

跨平台适配

Flutter与HarmonyOS集成

Flutter框架通过Flutter OpenHarmony社区的支持,已经能够较好地运行在HarmonyOS系统上。集成过程主要包含以下步骤:

创建Flutter项目

配置HarmonyOS构建

安装Flutter OpenHarmony插件

执行flutter build hap

生成HarmonyOS应用

平台特性适配

针对HarmonyOS系统的特性,我们进行了以下适配:

  1. 分布式能力:利用HarmonyOS的分布式特性,支持多设备协同
  2. 原子化服务:支持将应用功能拆分为独立的原子化服务
  3. 系统集成:与HarmonyOS的通知、设置等系统功能深度集成

核心代码适配

/// 火车票查询应用根组件
class TrainTicketApp extends StatelessWidget {
  /// 构造函数
  const TrainTicketApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '火车票查询',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
        appBarTheme: const AppBarTheme(
          backgroundColor: Colors.blue,
          elevation: 4,
          titleTextStyle: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            backgroundColor: Colors.blue,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12.0),
            ),
          ),
        ),
      ),
      debugShowCheckedModeBanner: false,
      home: const TrainTicketQueryScreen(),
    );
  }
}

总结

项目成果

通过本项目的开发,我们成功实现了以下目标:

  • ✅ 创建了一个功能完整的火车票查询应用
  • ✅ 验证了Flutter在鸿蒙系统上的可行性
  • ✅ 建立了清晰的项目架构和代码规范
  • ✅ 实现了响应式界面设计,适配多种设备

技术收获

在项目开发过程中,我们积累了以下技术经验:

  1. Flutter跨平台开发:掌握了一套代码多端部署的开发模式
  2. HarmonyOS适配:了解了Flutter在鸿蒙系统上的集成方法
  3. 组件化设计:实践了基于Widget的组件化开发思想
  4. 响应式UI:实现了适配不同屏幕尺寸的界面设计

未来展望

基于本项目的成功经验,后续可以考虑以下扩展方向:

  • 实时余票查询:接入真实12306数据,实现实时余票查询
  • 订单管理功能:添加订单查询、改签、退票等功能
  • 智能推荐:根据用户出行历史,智能推荐出行方案
  • 多语言支持:扩展支持英文、日文等多语言版本

开发建议

对于有意开展Flutter鸿蒙开发的同行,我们提供以下建议:

  1. 关注社区动态:Flutter OpenHarmony社区发展迅速,及时跟进最新进展
  2. 模块化设计:将应用功能拆分为独立模块,便于后续维护和扩展
  3. 充分测试:在真机上进行充分测试,确保各平台兼容性
  4. 性能优化:关注应用的性能表现,避免过度绘制和内存泄漏

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

Logo

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

更多推荐