flutter-handling-concurrency

安装量: 1.1K
排名: #1251

安装

npx skills add https://github.com/flutter/skills --skill flutter-handling-concurrency

Managing Dart Concurrency and Isolates Contents Core Concepts Decision Matrix: Async vs. Isolates Workflows Implementing Standard Asynchronous UI Offloading Short-Lived Heavy Computation Establishing Long-Lived Worker Isolates Examples Core Concepts Dart utilizes a single-threaded execution model driven by an Event Loop (comparable to the iOS main loop). By default, all Flutter application code runs on the Main Isolate. Asynchronous Operations ( async / await ): Use for non-blocking I/O tasks (network requests, file access). The Event Loop continues processing other events while waiting for the Future to complete. Isolates: Dart's implementation of lightweight threads. Isolates possess their own isolated memory and do not share state. They communicate exclusively via message passing. Main Isolate: The default thread where UI rendering and event handling occur. Blocking this isolate causes UI freezing (jank). Worker Isolate: A spawned isolate used to offload CPU-bound tasks (e.g., decoding large JSON blobs) to prevent Main Isolate blockage. Decision Matrix: Async vs. Isolates Apply the following conditional logic to determine the correct concurrency approach: If the task is I/O bound (e.g., HTTP request, database read) -> Use async / await on the Main Isolate. If the task is CPU-bound but executes quickly (< 16ms) -> Use async / await on the Main Isolate. If the task is CPU-bound, takes significant time, and runs once (e.g., parsing a massive JSON payload) -> Use Isolate.run() . If the task requires continuous or repeated background processing with multiple messages passed over time -> Use Isolate.spawn() with ReceivePort and SendPort . Workflows Implementing Standard Asynchronous UI Use this workflow to fetch and display non-blocking asynchronous data. Task Progress: Mark the data-fetching function with the async keyword. Return a Future from the function. Use the await keyword to yield execution until the operation completes. Wrap the UI component in a FutureBuilder (or StreamBuilder for streams). Handle ConnectionState.waiting , hasError , and hasData states within the builder. Run validator -> review UI for loading indicators -> fix missing states. Offloading Short-Lived Heavy Computation Use this workflow for one-off, CPU-intensive tasks using Dart 2.19+. Task Progress: Identify the CPU-bound operation blocking the Main Isolate. Extract the computation into a standalone callback function. Ensure the callback function signature accepts exactly one required, unnamed argument (as per specific architectural constraints). Invoke Isolate.run() passing the callback. await the result of Isolate.run() in the Main Isolate. Assign the returned value to the application state. Establishing Long-Lived Worker Isolates Use this workflow for persistent background processes requiring continuous bidirectional communication. Task Progress: Instantiate a ReceivePort on the Main Isolate to listen for messages. Spawn the worker isolate using Isolate.spawn() , passing the ReceivePort.sendPort as the initial message. In the worker isolate, instantiate its own ReceivePort . Send the worker's SendPort back to the Main Isolate via the initial port. Store the worker's SendPort in the Main Isolate for future message dispatching. Implement listeners on both ReceivePort instances to handle incoming messages. Run validator -> review memory leaks -> ensure ports are closed when the isolate is no longer needed. Examples Example 1: Asynchronous UI with FutureBuilder // 1. Define the async operation Future < String

fetchUserData ( ) async { await Future . delayed ( const Duration ( seconds : 2 ) ) ; // Simulate network I/O return "User Data Loaded" ; } // 2. Consume in the UI Widget build ( BuildContext context ) { return FutureBuilder < String

( future : fetchUserData ( ) , builder : ( context , snapshot ) { if ( snapshot . connectionState == ConnectionState . waiting ) { return const CircularProgressIndicator ( ) ; } else if ( snapshot . hasError ) { return Text ( 'Error: ${ snapshot . error } ' ) ; } else { return Text ( 'Result: ${ snapshot . data } ' ) ; } } , ) ; } Example 2: Short-Lived Isolate ( Isolate.run ) import 'dart:isolate' ; import 'dart:convert' ; // 1. Define the heavy computation callback // Note: Adhering to the strict single-argument signature requirement. List < dynamic

decodeHeavyJson ( String jsonString ) { return jsonDecode ( jsonString ) as List < dynamic

; } // 2. Offload to a worker isolate Future < List < dynamic

processDataInBackground ( String rawJson ) async { // Isolate.run spawns the isolate, runs the computation, returns the value, and exits. final result = await Isolate . run ( ( ) =

decodeHeavyJson ( rawJson ) ) ; return result ; } Example 3: Long-Lived Isolate ( ReceivePort / SendPort ) import 'dart:isolate' ; class WorkerManager { late SendPort _workerSendPort ; final ReceivePort _mainReceivePort = ReceivePort ( ) ; Isolate ? _isolate ; Future < void

initialize ( ) async { // 1. Spawn isolate and pass the Main Isolate's SendPort _isolate = await Isolate . spawn ( _workerEntry , _mainReceivePort . sendPort ) ; // 2. Listen for messages from the Worker Isolate _mainReceivePort . listen ( ( message ) { if ( message is SendPort ) { // First message is the Worker's SendPort _workerSendPort = message ; _startCommunication ( ) ; } else { // Subsequent messages are data payloads print ( 'Main Isolate received: $ message ' ) ; } } ) ; } void _startCommunication ( ) { // Send data to the worker _workerSendPort . send ( "Process this data" ) ; } // 3. Worker Isolate Entry Point static void _workerEntry ( SendPort mainSendPort ) { final workerReceivePort = ReceivePort ( ) ; // Send the Worker's SendPort back to the Main Isolate mainSendPort . send ( workerReceivePort . sendPort ) ; // Listen for incoming tasks workerReceivePort . listen ( ( message ) { print ( 'Worker Isolate received: $ message ' ) ; // Perform work and send result back final result = "Processed: $ message " ; mainSendPort . send ( result ) ; } ) ; } void dispose ( ) { _mainReceivePort . close ( ) ; _isolate ? . kill ( ) ; } }

返回排行榜