Flutter

Isolate 사용방법

flutter 개발하자 2021. 5. 31. 09:29

Isolate 사용 방법 

compute의 경우 다른 예제 글들이 많으니 넘어가고, spawn의 방법에대해 알아보자.

isolate간의 통신을 위한 방법은 RecievePort를 통해 하는 것인데, 

 

RecievePort

 - isolata간에 메세지를 주고 받을 수 있는 포트 

 - RecievePort는 sendPort를 반환하는 SendPort getter를 갖고 있음

 

SendPort

 - 지정된 RecievePort에 메세지를 보냄.

 - SendPort를 통해 전송된 메세지는 지정된 RecievePort에 전송되고, RecievePort는 해당 메세지를 RecievePort의 listener를 통해 받을 수 있다.

 

Isolate.spawn

Isolate.spawn(함수, recievePort.sendPort)

 - isolate를 생성하고, spawn의 첫 번째 인자로 들어온 함수를 실행시킴. 

(이때의 함수는 static이거나 top-level function이여야 한다.)

(top-level function은 클래스나 main함수 외에 선언된 함수를 의미함,)

ex)

void foo() {} // A top-level function

class A {
  static void bar() {} // A static method
  void baz() {} // An instance method
}

void main() {
  Function x;

  // Comparing top-level functions.
  x = foo;
  assert(foo == x);

  // Comparing static methods.
  x = A.bar;
  assert(A.bar == x);

  // Comparing instance methods.
  var v = A(); // Instance #1 of A
  var w = A(); // Instance #2 of A
  var y = w;
  x = w.baz;

  // These closures refer to the same instance (#2),
  // so they're equal.
  assert(y.baz == x);

  // These closures refer to different instances,
  // so they're unequal.
  assert(v.baz != w.baz);
}

 

 

late Isolate isolate;

 

RecievePort recievePort = RecievePort();

isolate = Isolate.spawn(함수, receivePort.sendPort);

reciecePort.listen(들어온 데이터 처리 함수, onDone:(){});

 

static 함수(){

   sendPort(데이터)

}

 

 

 

 

 

예제

import 'dart:async';
import 'package:flutter/material.dart';
import 'dart:isolate';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Isolate Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(key: null,title: 'Flutter Isolates'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({required Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late Isolate? _isolate;
  bool _running = false;
  static int _counter = 0;
  String notification = "";
  late ReceivePort _receivePort;

  void _start() async {
    _running = true;
    _receivePort = ReceivePort();
    _isolate = await Isolate.spawn(_checkTimer, _receivePort.sendPort);
    _receivePort.listen(_handleMessage, onDone:() {
      print("done!");
    });
  }

  void _checkTimer(SendPort sendPort) async {
    Timer.periodic(new Duration(seconds: 1), (Timer t) {
      _counter++;
      String msg = 'notification ' + _counter.toString();
      print('SEND: ' + msg);
      sendPort.send(msg);
    });
  }

  void _handleMessage(dynamic data) {
    print('RECEIVED: ' + data);
    setState(() {
      notification = data;
    });
  }

  void _stop() {
    if (_isolate != null) {
      setState(() {
        _running = false;
        notification = '';
      });
      _receivePort.close();
      _isolate!.kill(priority: Isolate.immediate);
      _isolate = null;
    }
  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              notification,
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _running ? _stop : _start,
        tooltip: _running ? 'Timer stop' : 'Timer start',
        child: _running ? new Icon(Icons.stop) : new Icon(Icons.play_arrow),
      ),
    );
  }
}