Flutter는 기본적으로 싱글 스레드(Single-threaded)모델을 사용합니다. 즉, 하나의 스레드에서 모든 작업을 처리하기 때문에 무거운 연산이 실행되면 UI가 멈출 수 있습니다. 이를 방지하기 위해 Isolate를 사용하면 메인 스레드와 독립적으로 실행되는 새로운 스레드에서 작업을 수행할 수 있습니다.
SendPort와 ReceivePort로 메시지를 주고받아야 합니다.Dart의 Isolate는 기본적으로 다음과 같은 구조로 동작합니다.
1. 메인 Isolate (UI 스레드)에서 새로운 Isolate를 생성
2. 새 Isolate가 독립적으로 실행되며, 자신만의 힙 메모리를 가짐
3. 데이터 공유는 SendPort와 ReceivePort를 사용하여 메시지를 주고받는 방식으로 처리
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String result = '버튼을 눌러 계산 시작';
bool isLoading = false;
void _calculateHeavyTask() {
setState(() {
result = '계산 중...';
});
List<int> numbers = List.generate(5000000, (index) => index);
List<int> squaredNumbers = numbers.map((n) => n * n).toList();
setState(() {
result = "계산 완료! 첫 5개: ${squaredNumbers.sublist(0, 5)}";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
Text(result),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _calculateHeavyTask,
child: Icon(Icons.calculate),
),
);
}
}
버튼을 클릭했을때 로딩 애니메이션이 결과가 나오기 전에는 멈춤
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String result = '버튼을 눌러 계산 시작';
ReceivePort _receivePort = ReceivePort();
late final _isolate;
@override
void initState() {
super.initState();
_receivePort.listen((message) {
setState(() {
result = message;
});
},);
}
void _calculateHeavyTask() async {
setState(() {
result = '계산 중...';
});
_isolate = await Isolate.spawn(_isolateTask, _receivePort.sendPort);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
Text(result),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _calculateHeavyTask,
child: Icon(Icons.calculate),
),
);
}
}
void _isolateTask(SendPort sendPort) {
List<int> numbers = List.generate(5000000, (index) => index);
List<int> squaredNumbers = numbers.map((n) => n * n).toList();
sendPort.send("계산 완료! 첫 5개: ${squaredNumbers.sublist(0, 5)}");
}
Isolate를 적용한 경우에는 로딩 애니메이션이 멈추지 않음