商店現已上線

我們打造用於網站、AI 智慧體和 LLM 訓練的 Workstation AI 機器——線上配置併購買。

獲取同行價格
AI 產品
AI 實驗室OpenAI 智慧體Claude 代理Grok BotWorkstation AI 原生 CRM營銷所有產品
AI 解決方案
應用型 AIAI 智慧體生成式 AIAI 自動化AI 技能提升中小企業 AI 套餐企業 AI 實驗室AI 工作站NVIDIA 硬體與軟體NVIDIA 加速計算私有 AIGPU 私有云GPU 叢集邊緣 AI行業 AI
AI 服務
平臺現代化數字工程資料基礎與 AI自主運營AI 諮詢DevOps 自動化網路安全軟體開發智慧體構建MLOps 搭建GPU 租賃GPU 私有云
關於我們
公司我們的故事合作伙伴客戶案例
AI 資料中心
AI 資料中心GPU 私有云GPU 叢集GPU 租賃
AI 洞察Jev 系列基準測試實驗室模型選擇
技術說明
文件
Linux 作業系統UbuntuRed Hat Enterprise LinuxSUSE LinuxAlpine LinuxDebian、Rocky 與 AlmaLinux
AI 雲平臺AWS 與 Amazon BedrockGoogle Cloud 與 Vertex AIMicrosoft Azure 與 AI FoundryGPU 雲與算力市場
私有 AI 資料中心面向律師事務所面向會計師事務所本地部署平臺全面安全的雲
工具Ring PromoterJobshout
新聞
部落格
聯絡我們登入

面向現代企業的 AI 工作站、AI 多智慧體軟體、GPU 基礎設施和智慧代理解決方案。

聯絡我們

AI 解決方案

應用型 AIAI 智慧體生成式 AIAI 自動化AI 技能提升中小企業 AI 套餐企業 AI 實驗室行業 AI

產品

所有產品Workstation AI native CRM 與 ERP營銷OpenAI 智慧體Ring PromoterJobshout

公司

關於我們公司AI 資料中心為什麼選擇Workstation合作伙伴客戶案例定價聯絡TenthMatrix

資源

AI 洞察技術說明文件Linux 作業系統AI 雲平臺私有 AI 資料中心部落格搜尋網站地圖
英國總部
77-79 Marlowes, Hemel Hempstead HP1 1LF路線指引 — 從 M25 外環倫敦 20 號出口駛出公司編號: 11641870週一至週五:上午 9:00 - 下午 6:00 GMT
+44 7515 356 146
比利時辦公室
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683週一至週五:上午 9:00 - 下午 6:00 CET
+32 492 45 67 46
印度辦公室
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841
台灣辦公室
3F, No. 2-4, Aisi Rd., Ren'ai Dist., Keelung City 200, Taiwan基隆市仁愛區愛四路2之4號3樓週一至週五:上午 9:00 - 下午 6:00 臺灣時間(GMT+8)
+886 926 892 701+32 492 45 67 46

© 2026 Workstation AI。保留所有權利。

隱私資料刪除Cookie服務條款網站地圖

NVIDIA、NVIDIA 標誌、RTX、RTX PRO、Blackwell、CUDA、NVLink、MGX、Omniverse、Spectrum-X、Quantum、BlueField、DGX 與 HGX 為 NVIDIA Corporation 在美國及其他國家的商標及/或註冊商標。AMD、AMD Arrow 標誌、EPYC、Instinct、Ryzen 與 Threadripper 為 Advanced Micro Devices, Inc. 的商標。Dell 與 PowerEdge 為 Dell Inc. 或其子公司的商標。Intel 與 Xeon 為 Intel Corporation 或其子公司的商標。AMAX、AceleMax 與 LiquidMax 為 AMAX Engineering Corporation 的商標。所有其他產品名稱、標誌與品牌均為其各自所有者之財產。我們使用它們僅為識別我們所描述、供應或支援的產品;使用這些名稱並不表示其所有者為我們背書。

Loading blog...

首頁 / 部落格
MysqlNode.jsBackend

掌握 Flutter:構建生產就緒的移動應用程式

使用 Flutter 和 Dart 構建強大、可擴充套件的移動應用程式的完整指南

Balinder Walia2025年5月27日5 min read
35

構建 Flutter 原型很容易。構建可擴充套件、在負載下效能良好且可多年維護的生產就緒型 Flutter 應用程式需要對架構、狀態管理、測試和部署工作流程有更深入的瞭解。本指南彌合了教程專案和實際應用程式之間的差距,涵蓋了專業 Flutter 團隊每天依賴的模式和實踐。適用於 Flutter 的

Clean 架構

Clean 架構將您的應用程式分為具有清晰邊界和依賴關係規則的不同層。這種分離使您的程式碼可測試、可維護並且獨立於外部框架和工具。

Flutter 架構層您的 Dart 程式碼業務邏輯和功能UI 組成Flutter 框架小元件渲染基礎(手勢、動畫)引擎 (C++)Skia 顯示卡Dart 執行時 •平臺通道iOS (UIKit)ARM / Apple SiliconAndroid (NDK)ARM / x86

層結構

生產型 Flutter 應用程式通常遵循三層架構:

  • 表示層- 小部件、頁面和狀態管理。該層依賴於領域層,但從不直接依賴於資料來源。
  • 域層- 業務邏輯、實體和用例。該層對 Flutter 或任何外部包的依賴為零。它定義了資料層實現的儲存庫介面(抽象類)。
  • 資料層- 儲存庫實現、API 客戶端、本地資料庫訪問和資料模型 (DTO)。該層實現領域層中定義的介面。
lib/
  core/
    error/
      exceptions.dart
      failures.dart
    network/
      network_info.dart
    usecases/
      usecase.dart
  features/
    authentication/
      data/
        datasources/
          auth_remote_datasource.dart
          auth_local_datasource.dart
        models/
          user_model.dart
        repositories/
          auth_repository_impl.dart
      domain/
        entities/
          user.dart
        repositories/
          auth_repository.dart
        usecases/
          login.dart
          register.dart
          logout.dart
      presentation/
        bloc/
          auth_bloc.dart
          auth_event.dart
          auth_state.dart
        pages/
          login_page.dart
          register_page.dart
        widgets/
          login_form.dart

依賴關係規則很嚴格:內層永遠不知道外層。領域層定義抽象儲存庫介面,資料層提供具體實現。這種控制反轉允許您交換資料來源而無需觸及業務邏輯。

狀態管理:BLoC 和 Riverpod

選擇正確的狀態管理解決方案是 Flutter 專案中最有影響力的架構決策之一。

BLoC 模式

BLoC(業務邏輯元件)使用流來管理狀態。事件流入,狀態流出。這種單向資料流使狀態變化可預測且易於除錯。

// Events
abstract class AuthEvent {}

class LoginRequested extends AuthEvent {
  final String email;
  final String password;
  LoginRequested({required this.email, required this.password});
}

class LogoutRequested extends AuthEvent {}

// States
abstract class AuthState {}

class AuthInitial extends AuthState {}
class AuthLoading extends AuthState {}
class AuthAuthenticated extends AuthState {
  final User user;
  AuthAuthenticated(this.user);
}
class AuthError extends AuthState {
  final String message;
  AuthError(this.message);
}

// BLoC
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final LoginUseCase loginUseCase;
  final LogoutUseCase logoutUseCase;

  AuthBloc({
    required this.loginUseCase,
    required this.logoutUseCase,
  }) : super(AuthInitial()) {
    on<LoginRequested>(_onLoginRequested);
    on<LogoutRequested>(_onLogoutRequested);
  }

  Future<void> _onLoginRequested(
    LoginRequested event,
    Emitter<AuthState> emit,
  ) async {
    emit(AuthLoading());
    final result = await loginUseCase(
      LoginParams(email: event.email, password: event.password),
    );
    result.fold(
      (failure) => emit(AuthError(failure.message)),
      (user) => emit(AuthAuthenticated(user)),
    );
  }

  Future<void> _onLogoutRequested(
    LogoutRequested event,
    Emitter<AuthState> emit,
  ) async {
    await logoutUseCase();
    emit(AuthInitial());
  }
}

Riverpod

Riverpod 提供更靈活、編譯安全的狀態管理方法。與 Provider 不同,Riverpod 不依賴於 widget 樹,從而更容易測試和組合。

// Define providers
final authRepositoryProvider = Provider<AuthRepository>((ref) {
  return AuthRepositoryImpl(
    remoteDatasource: ref.read(authRemoteDatasourceProvider),
    localDatasource: ref.read(authLocalDatasourceProvider),
  );
});

final authStateProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
  return AuthNotifier(ref.read(authRepositoryProvider));
});

class AuthNotifier extends StateNotifier<AuthState> {
  final AuthRepository _repository;

  AuthNotifier(this._repository) : super(const AuthState.initial());

  Future<void> login(String email, String password) async {
    state = const AuthState.loading();
    final result = await _repository.login(email, password);
    state = result.fold(
      (failure) => AuthState.error(failure.message),
      (user) => AuthState.authenticated(user),
    );
  }
}

// Use in widgets
class LoginPage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final authState = ref.watch(authStateProvider);
    return authState.when(
      initial: () => LoginForm(),
      loading: () => const CircularProgressIndicator(),
      authenticated: (user) => HomePage(user: user),
      error: (message) => ErrorDisplay(message: message),
    );
  }
}

依賴項注入

正確的依賴項注入對於可測試程式碼至關重要。get_it軟體包提供了一個簡單的服務定位器,可以很好地與乾淨的架構配合使用。

Flutter 小部件樹MaterialApp支架柱AppBarListViewFABListTile 1ListTile 2
final sl = GetIt.instance;

void initDependencies() {
  // External
  sl.registerLazySingleton(() => Dio()..interceptors.add(AuthInterceptor()));
  sl.registerLazySingleton(() => InternetConnectionChecker());

  // Data sources
  sl.registerLazySingleton<AuthRemoteDatasource>(
    () => AuthRemoteDatasourceImpl(dio: sl()),
  );
  sl.registerLazySingleton<AuthLocalDatasource>(
    () => AuthLocalDatasourceImpl(secureStorage: sl()),
  );

  // Repositories
  sl.registerLazySingleton<AuthRepository>(
    () => AuthRepositoryImpl(
      remoteDatasource: sl(),
      localDatasource: sl(),
      networkInfo: sl(),
    ),
  );

  // Use cases
  sl.registerLazySingleton(() => LoginUseCase(sl()));
  sl.registerLazySingleton(() => RegisterUseCase(sl()));

  // BLoCs
  sl.registerFactory(() => AuthBloc(
    loginUseCase: sl(),
    logoutUseCase: sl(),
  ));
}

API 與 Dio 整合

Dio 是最流行的 Dart HTTP 客戶端,提供攔截器、全域性配置和 FormData 支援。使用型別安全的請求和響應處理來構建 API 層。

class ApiClient {
  final Dio _dio;

  ApiClient(this._dio) {
    _dio.options = BaseOptions(
      baseUrl: Environment.apiBaseUrl,
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 15),
      headers: {'Content-Type': 'application/json'},
    );

    _dio.interceptors.addAll([
      AuthInterceptor(),
      LogInterceptor(requestBody: true, responseBody: true),
      RetryInterceptor(dio: _dio, retries: 3),
    ]);
  }

  Future<T> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    required T Function(dynamic data) parser,
  }) async {
    try {
      final response = await _dio.get(path, queryParameters: queryParameters);
      return parser(response.data);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  AppException _handleError(DioException error) {
    switch (error.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.receiveTimeout:
        return NetworkException('Connection timed out');
      case DioExceptionType.badResponse:
        return ServerException(
          error.response?.statusCode ?? 500,
          error.response?.data?['message'] ?? 'Unknown error',
        );
      default:
        return NetworkException('Network error occurred');
    }
  }
}

具有 Hive 和 Sqflite 的本地儲存

大多數生產應用程式需要本地資料永續性。根據您的資料複雜性選擇正確的工具。

Hive,用於鍵值和物件儲存

Hive 是一個用純 Dart 編寫的輕量級、速度極快的 NoSQL 資料庫。它非常適合快取、使用者首選項和儲存中小型資料集。

@HiveType(typeId: 0)
class CachedArticle extends HiveObject {
  @HiveField(0)
  final String id;

  @HiveField(1)
  final String title;

  @HiveField(2)
  final String content;

  @HiveField(3)
  final DateTime cachedAt;

  CachedArticle({
    required this.id,
    required this.title,
    required this.content,
    required this.cachedAt,
  });
}

class ArticleCacheService {
  static const _boxName = 'articles_cache';

  Future<void> cacheArticles(List<Article> articles) async {
    final box = await Hive.openBox<CachedArticle>(_boxName);
    final cached = articles.map((a) => CachedArticle(
      id: a.id,
      title: a.title,
      content: a.content,
      cachedAt: DateTime.now(),
    ));
    await box.clear();
    await box.addAll(cached);
  }

  Future<List<CachedArticle>> getCachedArticles() async {
    final box = await Hive.openBox<CachedArticle>(_boxName);
    return box.values.toList();
  }
}

用於關係資料的 Sqflite

當您的資料具有複雜關係並且需要 SQL 查詢時,Sqflite 為 Flutter 提供完整的 SQLite 實現。將其用於受益於聯接、索引和事務的結構化資料。

推送通知

使用 Firebase 雲訊息傳遞 (FCM) 以及適當的許可權處理和後臺訊息處理來實現推送通知。

class NotificationService {
  final FirebaseMessaging _messaging = FirebaseMessaging.instance;

  Future<void> initialize() async {
    // Request permission
    final settings = await _messaging.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );

    if (settings.authorizationStatus == AuthorizationStatus.authorized) {
      // Get FCM token
      final token = await _messaging.getToken();
      await _sendTokenToServer(token);

      // Listen for token refresh
      _messaging.onTokenRefresh.listen(_sendTokenToServer);

      // Handle foreground messages
      FirebaseMessaging.onMessage.listen(_handleForegroundMessage);

      // Handle background/terminated message taps
      FirebaseMessaging.onMessageOpenedApp.listen(_handleMessageTap);
    }
  }

  void _handleForegroundMessage(RemoteMessage message) {
    // Show local notification using flutter_local_notifications
    FlutterLocalNotificationsPlugin().show(
      message.hashCode,
      message.notification?.title,
      message.notification?.body,
      const NotificationDetails(
        android: AndroidNotificationDetails(
          'default_channel',
          'Default',
          importance: Importance.high,
        ),
      ),
    );
  }
}

深層連結

深層連結允許使用者從外部 URL 直接導航到應用程式內的特定內容。 Flutter同時支援基於URI的深度連結和動態連結。

// Configure in MaterialApp
MaterialApp(
  onGenerateRoute: (settings) {
    final uri = Uri.parse(settings.name ?? '');

    if (uri.pathSegments.first == 'product') {
      final productId = uri.pathSegments[1];
      return MaterialPageRoute(
        builder: (_) => ProductDetailPage(id: productId),
      );
    }

    if (uri.pathSegments.first == 'order') {
      final orderId = uri.pathSegments[1];
      return MaterialPageRoute(
        builder: (_) => OrderTrackingPage(id: orderId),
      );
    }

    return MaterialPageRoute(builder: (_) => const HomePage());
  },
)

要獲得更強大的深度連結,請使用go_router軟體包,該軟體包提供具有深度連結支援、重定向和巢狀導航的宣告式路由。

帶 Codemagic 和 Fastlane 的 CI/CD

自動化構建和部署管道對於生產應用程式至關重要。 Codemagic 提供 Flutter 原生 CI/CD 服務,而 Fastlane 提供更多可定製的自動化。

Codemagic 配置

# codemagic.yaml
workflows:
  production-release:
    name: Production Release
    max_build_duration: 60
    environment:
      flutter: stable
      vars:
        APP_STORE_CONNECT_KEY_ID: Encrypted(...)
        GOOGLE_PLAY_SERVICE_ACCOUNT: Encrypted(...)
    scripts:
      - name: Install dependencies
        script: flutter pub get
      - name: Run tests
        script: flutter test --coverage
      - name: Build Android
        script: flutter build appbundle --release
      - name: Build iOS
        script: |
          flutter build ipa --release \
            --export-options-plist=/path/to/ExportOptions.plist
    artifacts:
      - build/**/outputs/**/*.aab
      - build/ios/ipa/*.ipa
    publishing:
      google_play:
        credentials: $GOOGLE_PLAY_SERVICE_ACCOUNT
        track: internal
      app_store_connect:
        api_key: $APP_STORE_CONNECT_KEY_ID

Fastlane 整合

Fastlane 提供對構建和提交過程的精細控制。為不同的釋出階段定義通道:

# fastlane/Fastfile
platform :ios do
  desc "Deploy to TestFlight"
  lane :beta do
    build_flutter_app(target: "lib/main.dart")
    upload_to_testflight(
      skip_waiting_for_build_processing: true
    )
  end

  desc "Deploy to App Store"
  lane :release do
    build_flutter_app(target: "lib/main.dart")
    upload_to_app_store(
      submit_for_review: true,
      automatic_release: false
    )
  end
end

效能分析

生產應用程式需要一致的效能。 Flutter DevTools 提供全面的分析功能。

  • 小部件重建跟蹤- 使用效能覆蓋和開發工具來識別過度重建的小部件。應用const建構函式和選擇性狀態管理來最大限度地減少重建。
  • 幀渲染- 監控時間線檢視以確保幀在 16ms (60fps) 或 8ms (120fps) 內渲染。尋找昂貴的構建、佈局和油漆階段。
  • 記憶體分析- 跟蹤記憶體分配以檢測洩漏。常見的罪魁禍首包括未取消的流訂閱、未處理的控制器和閉包中保留的引用。
  • 啟動效能- 使用WidgetsBinding.instance.addPostFrameCallback推遲繁重的初始化。對於不立即需要的功能,使用deferred as匯入的延遲載入。
// Profile-mode build for accurate performance measurement
// flutter run --profile

// Add performance overlay in debug builds
MaterialApp(
  showPerformanceOverlay: true,
  // ...
)

結論

構建可投入生產的 Flutter 應用程式需要的不僅僅是瞭解小部件目錄。 它需要深思熟慮的架構、強大的狀態管理、全面的測試和自動化部署管道。透過採用乾淨的架構、投資適當的依賴項注入、實施徹底的錯誤處理以及建立 CI/CD 工作流程,您建立的應用程式不僅可以正常執行,而且可以長期維護和擴充套件。

首先儘早建立架構,從第一天開始編寫測試,並在首次釋出之前自動化部署管道。隨著時間的推移,這些前期投資會不斷增加,使您的團隊能夠更快地釋出功能,減少迴歸,並對每個版本更有信心。