Flutter 線程模型詳解:主線程、異步與 Isolate


一、主線程:默認的執行環境

所有代碼默認運行在主線程。下面的例子展示了一個會阻塞主線程的錯誤示范:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return MaterialApp(home: HomePage(),);}
}class HomePage extends StatefulWidget {State<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {String _result = '點擊按鈕開始計算';bool _isLoading = false;// 一個模擬的、非常耗時的同步計算函數// 這會嚴重阻塞主線程!int _expensiveTask(int number) {int sum = 0;for (int i = 0; i < number; i++) {sum += i;}return sum;}void _doTaskOnMainThread() {setState(() {_isLoading = true;});// 這個計算直接在UI線程上運行,會導致界面卡死int result = _expensiveTask(10000000000); // 一個很大的數setState(() {_result = '計算結果: $result';_isLoading = false;});}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('線程模型實戰')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [if (_isLoading) const CircularProgressIndicator(),Text(_result, style: Theme.of(context).textTheme.headlineSmall),ElevatedButton(onPressed: _doTaskOnMainThread,// 點擊這個按鈕后,UI會完全卡住,連Loading圈都無法轉動child: const Text('在主線程執行耗時任務 (錯誤示范)'),),],),),);}
}

現象:點擊按鈕后,即使看到了 Loading 圓圈,它也會完全凍結,無法動畫,直到計算完成。這就是阻塞主線程的后果。


二、異步操作:處理 I/O 任務(網絡請求為例)

使用 async/await 和 Future 處理不會阻塞線程的“等待型”任務。

// ... 承接上面的 State class ...// 在 _HomePageState 類中添加新方法
Future<void> _fetchDataAsync() async {setState(() {_isLoading = true;_result = '正在加載...';});// 使用 async/await 進行異步網絡請求// http.get 是非阻塞的,它向系統發出請求后就直接返回了try {// 記得添加 http 包: flutter pub add http// import 'package:http/http.dart' as http;final response = await http.get(Uri.parse('https://api.example.com/data'));// 這里的代碼會在網絡請求成功后,由事件循環調度執行// 它仍然運行在主線程,但等待期間主線程是空閑的,可以處理其他事件(如動畫)if (response.statusCode == 200) {setState(() {_result = '獲取成功: ${response.body.substring(0, 100)}...';});} else {setState(() {_result = '請求失敗: ${response.statusCode}';});}} catch (e) {setState(() {_result = '發生錯誤: $e';});} finally {setState(() {_isLoading = false;});}
}// 在 build 方法的 Column 中添加新的按鈕
ElevatedButton(onPressed: _fetchDataAsync,child: const Text('執行異步網絡請求 (正確示范)'),
),

現象:點擊按鈕后,Loading 圓圈流暢旋轉,UI 可以正常響應。數據獲取完成后,結果會更新到屏幕上。


三、Isolate:處理 CPU 密集型任務

使用 compute 函數將耗時計算任務移到后臺 Isolate。

// 1. 首先,在文件頂部導入 foundation.dart
import 'package:flutter/foundation.dart';// 2. 確保耗時函數是頂級函數或靜態方法
// 因為 Isolate 不能訪問原實例中的非靜態成員
int _expensiveTaskInIsolate(int number) {int sum = 0;for (int i = 0; i < number; i++) {sum += i;}return sum;
}// 3. 在 _HomePageState 類中添加新方法
void _doTaskInIsolate() async {setState(() {_isLoading = true;_result = '在Isolate中計算...';});// 使用 compute 將函數和參數拋到新的Isolate中執行// 這是一個非阻塞調用,會立即返回一個Futureint result = await compute(_expensiveTaskInIsolate, 10000000000);// compute 完成后,這里的代碼會在主線程執行,可以安全地更新UIsetState(() {_result = 'Isolate計算結果: $result';_isLoading = false;});
}// 4. 在 build 方法的 Column 中添加新的按鈕
ElevatedButton(onPressed: _doTaskInIsolate,child: const Text('使用Isolate執行計算 (正確示范)'),
),

現象:點擊按鈕后,Loading 圓圈流暢旋轉,UI 操作完全正常,毫無卡頓。計算完成后,結果會更新到屏幕上。


最終效果對比

你的 build 方法中的 Column 最終會有三個按鈕:

Column(mainAxisAlignment: MainAxisAlignment.center,children: [if (_isLoading) const CircularProgressIndicator(),Text(_result, style: Theme.of(context).textTheme.headlineSmall),ElevatedButton(onPressed: _doTaskOnMainThread,child: const Text('在主線程執行耗時任務 (錯誤示范)'),),SizedBox(height: 10),ElevatedButton(onPressed: _fetchDataAsync,child: const Text('執行異步網絡請求 (正確示范)'),),SizedBox(height: 10),ElevatedButton(onPressed: _doTaskInIsolate,child: const Text('使用Isolate執行計算 (正確示范)'),),],
)

總結一下:

· 錯誤示范按鈕:會讓你體驗到應用卡死的糟糕感覺。
· 異步網絡請求按鈕:展示了如何用 async/await 正確處理 I/O 操作。
· Isolate 計算按鈕:展示了如何用 compute 正確處理 CPU 密集型任務。

通過這個實戰對比,你能清晰地看到三種方式的巨大差異,并理解在正確場景使用正確工具的重要性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/96287.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/96287.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/96287.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ChartDB:可視化數據庫設計工具私有化部署

ChartDB:可視化數據庫設計工具私有化部署一、什么是ChartDB ChartDB 是一款基于 Web 的開源數據庫可視化工具&#xff0c;專為簡化數據庫設計與管理流程而開發。以下是其核心特性與功能概述: 1、核心功能 智能查詢可視化?&#xff1a;通過單條 SQL 查詢即可生成數據庫架構圖&a…

單片機-FreeRTOS(ing)

目錄 一、基礎介紹 1.1 調度策略 1.1.1 調度方式 1.1.2 調度器 1.2 任務以及優先級 1.2.1 任務與協程 1.2.2 任務狀態 1.2.3 任務優先級 1.2.4 任務優先級分配方案 1.3 任務間通信 - 信號量 1.3.1 信號量 1.3.2 任務間計數信號量的實現 1.3.3 中斷方式計數信號量的…

為什么調用API總返回404,該如何調試

當調用一個應用程序接口&#xff08;API&#xff09;時&#xff0c;持續地收到“404 未找到”的錯誤&#xff0c;其核心原因在于客戶端發起的“請求”&#xff0c;未能成功地&#xff0c;匹配到服務器上任何一個“真實存在”的、可供訪問的“資源路徑”。這本質上&#xff0c;是…

醫療信息化自主可控轉型的實踐探索 —— 以常德二院為例

目錄 頭雁領航 - 激發醫療新質生產力 核心支撐 - 電科金倉奠定數據底座 生態共建 - 攜手護航醫療信創發展 信創產業發展是國家經濟數字化轉型、提升產業鏈發展的關鍵&#xff0c;是科技自立自強的核心基座&#xff0c;其本質是實現中國信息化產業的自主可控。醫療信創作為關…

Gin傳參和接收參數的方式

Gin查詢參數和接收參數的方式 常用 Gin 綁定方法對比方法用途特點c.Bind()自動識別 Content-Type最通用&#xff0c;根據請求頭自動選擇綁定方式c.ShouldBindJSON()只綁定 JSON強制使用 JSON 格式&#xff0c;類型明確c.ShouldBindXML()只綁定 XML強制使用 XML 格式c.ShouldBin…

MariaDB/MySQL 客戶端工具與服務端配置精要指南

文章目錄一、客戶端與服務端程序二、用戶賬號管理三、MySQL 客戶端命令3.1 命令類型?3.2 使用模式?3.3 常用選項?3.4 提示符定制?四、mysqladmin管理命令??五、服務端配置?5.1 配置文件???5.2 Socket 通信配置??六、最佳實踐總結免費個人運維知識庫&#xff0c;歡迎…

自動化項目日報生成工具測評與選型:如何匹配團隊日報管理需求

引言在項目管理場景中&#xff0c;手動撰寫日報常面臨多重效率瓶頸&#xff1a;任務數據分散在協作群、Excel 表格、項目看板等多個平臺&#xff0c;匯總時需反復核對&#xff1b;不同成員日報格式不統一&#xff0c;管理層整合分析耗時&#xff1b;任務進度與日報信息不同步&a…

基于SpringBoot+Vue的吳韻蘇香文旅小程序(協同過濾算法、Echarts圖形化分析、騰訊地圖API、二維碼識別)

&#x1f388;系統亮點&#xff1a;協同過濾算法、Echarts圖形化分析、騰訊地圖API、二維碼識別&#xff1b;一.系統開發工具與環境搭建1.系統設計開發工具后端使用Java編程語言的Spring boot框架 項目架構&#xff1a;B/S架構 運行環境&#xff1a;win10/win11、jdk17小程序&a…

python numpy.random的基礎教程(附opencv 圖片轉數組、數組轉圖片)

目錄 1.在區間[a,b)隨機生成n個整數。 2.在區間[a,b)隨機生成n個數。 3.在區間[0,1)生成隨機數 4.打亂順序 5.從指定的列表中選擇 NumPy&#xff08;Numerical Python&#xff09;是一個開源的科學計算庫&#xff0c;專門用于高效處理多維數組&#xff08;ndarray&#xf…

Vue2.x核心技術與實戰(二)

目錄 三、Vue2.x:生命周期+工程化開發(組件入門) 3.1 生命周期 3.1.1 生命周期 & 生命周期四個階段 3.1.2 生命周期鉤子 Vue生命周期鉤子案例 - 新聞列表 & 輸入框自動聚焦 3.2 綜合案例:小黑記賬清單 3.3 工程化開發入門 3.3.1 工程化開發 & 腳手架Vue …

【鴻蒙心跡】7×24小時極限求生:當Origin_null遇上鴻蒙,我如何用100杯咖啡換一條跨域活路?

文章概要 大家好&#xff0c;我是那個把黑眼圈熬成華為工牌掛繩的倒霉蛋。過去100個夜晚&#xff0c;我在HarmonyOS NEXT的ArkWeb里被Origin:null反復按在地上摩擦——小程序白屏、OPTIONS 400、官方文檔沉默三連擊。最終&#xff0c;我用C、libcurl、OpenSSL和一堆速溶咖啡&am…

【git】刪除一條本地提交的歷史commit

在工程中&#xff0c;如果想要刪除一條本地提交的歷史commit&#xff0c;可以通過droprebase -i HEAD^n的方式。1.情景提交了三條commit&#xff0c;想刪掉第二條commit。git logcommit_id_*******1 commit_id_*******2 commit_id_*******32.解決git rebase -i HEAD~2輸出&…

軟件測試中,JMeter 的作用以及優缺點是什么?

回答重點JMeter 是一款開源的軟件測試工具&#xff0c;主要用來對各種軟件或服務進行性能測試和負載測試。它可以模擬大量用戶同時對服務器、網絡或其他資源發起請求&#xff0c;從而測試它們的響應時間、吞吐量等性能指標。優點&#xff1a;1&#xff09; 開源且免費 &#xf…

STM32存儲結構

我們在使用Keil編譯程序成功后會,有一行各部分占用內存的提示信息,如下Program Size:Code7492 RO-data556 Rw-data72 ZI-data11688,這是stm32代碼編譯后的提示我們分析一下這個編譯輸出&#xff1a;- Code: 7492字節 -> 代碼部分&#xff08;存放在Flash&#xff09;- RO-da…

手機 瀏覽器調用攝像頭掃描二維碼Quagga

注&#xff1a;需用谷歌瀏覽器才能調用權限1. 引入依賴&#xff1a;npm install ericblade/quagga2<template><el-button color"#188ae2" click"handleScan" class"scan-btn" :disabled"isInitializing || isScanning">{{…

【Oracle篇】偽列之Version Query:全鏈路追蹤行數據變更的所有記錄(不僅僅是被修改的最后時間)(第二篇,總共六篇)

&#x1f4ab;《博主主頁》&#xff1a;    &#x1f50e; CSDN主頁__奈斯DB    &#x1f50e; IF Club社區主頁__奈斯、 &#x1f525;《擅長領域》&#xff1a;擅長阿里云AnalyticDB for MySQL(分布式數據倉庫)、Oracle、MySQL、Linux、prometheus監控&#xff1b;并對…

代理模式深度解析:從靜態代理到 Spring AOP 實現

代理模式是軟件開發中一種經典的設計模式&#xff0c;它通過引入 "代理對象" 間接訪問目標對象&#xff0c;從而在不修改目標對象代碼的前提下&#xff0c;實現功能增強&#xff08;如日志記錄、事務管理&#xff09;、權限控制等橫切需求。從簡單的靜態代理到靈活的…

算法 ----- 鏈式

目錄 一 、鏈式 二 、題目 1、兩兩相加 &#xff08;1&#xff09;題目 (3) 代碼書寫 2、兩兩交換鏈表中的節點 &#xff08;1&#xff09;題目 &#xff08;2&#xff09; 解題思路 &#xff08;3&#xff09;代碼書寫 3、重排鏈表 &#xff08;1&#xff09;題目 …

運維監控prometheus+grafana

目錄 一、環境 二、Node_exporter部署 三、Prometheus部署 四、Grafana部署 五、驗證、使用 一、環境 系統使用CentOS7虛擬機。 監控三臺服務器&#xff1a; 192.168.114.10 Node1 #部署Prometheus、node_exporter、Grafana 192.168.114.20 Node2 …

數字孿生 :提高制造生產力的智能方法

近年來&#xff0c;在先進數字技術深度整合的推動下&#xff0c;制造業經歷了深刻變革。數字孿生技術作為其中最具前景的創新之一&#xff0c;正重塑工廠和生產流程的設計、監控和優化方式。該技術的核心在于為物理資產、系統或流程創建虛擬映射。這種虛擬映射實時同步現實世界…