Flutter实战项目-第十二篇 多线程isolate

概要

  • isolate
  • UI阻塞

一、dart线程概念

        dart语言默认是单线程的,这就导致了如果在处理一个耗时比较长事务的话,很有可能会造成UI渲染的阻塞。举例子:我在页面创建一个动画,然后执行一个计算的函数,而这个计算的函数耗时比较长,这个时候你就可以看到,动画在UI上会被卡住,直到计算函数执行完毕动画恢复正常。

import 'dart:isolate';

import 'package:flutter/material.dart';

class IsolateTest extends StatefulWidget {
  const IsolateTest({Key? key}) : super(key: key);

  @override
  State<IsolateTest> createState() => _IsolateTestState();
}

class _IsolateTestState extends State<IsolateTest> {
  int _count = 0;

  //耗时工作,计算偶数个数
  static int calculateEvenCount(int num) {
    int count = 0;
    while (num > 0) {
      if (num % 2 == 0) {
        count++;
      }
      num--;
    }
    return count;
  }


  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 100,
            height: 100,
            child: CircularProgressIndicator(),
          ),
          Text(_count.toString()),
          TextButton(
            onPressed: () {
              //触发耗时操作
              _count = calculateEvenCount(1000000000);
              setState(() {});
            },
            child: Text('开始耗时工作[在主线程]'),
          )
        ],
      ),
    );
  }
}

二、isolate

在dart 2.15以前,isolate是一个独立的包,在pub可以下载。在dart2.15后它已经集成在了sdk里面,不需要在单独下载包了。它是dart官方针对多线程给出的解决方案。它可以不占用主线程的情况下,另开线程去执行相应事务。但是这个isolate每个会消耗2m的内存资源,需要按实际场景具体谨慎使用。一下是对比效果代码。

首先我们创建一个线程管理

import 'dart:isolate';

class ThreadManagement {
  //entryPoint 必须是静态方法
  static Future<void> runTask<T>(void Function(SendPort message) entryPoint, Function(T value) callback, {Object? parameter}) async {
    final response = ReceivePort();
    Isolate d = await Isolate.spawn(entryPoint, response.sendPort);
    // 调用sendReceive自定义方法
    if (parameter != null) {
      SendPort sendPort = await response.first;
      ReceivePort receivePort = ReceivePort();
      sendPort.send([parameter, receivePort.sendPort]);
      receivePort.listen((value) {
        receivePort.close();
        d.kill();
        callback(value);
      });
    } else {
      response.listen((value) {
        response.close();
        d.kill();
        callback(value);
      });
    }
  }
}

页面调用

import 'dart:isolate';

import 'package:flutter/material.dart';

class IsolateTest extends StatefulWidget {
  const IsolateTest({Key? key}) : super(key: key);

  @override
  State<IsolateTest> createState() => _IsolateTestState();
}

class _IsolateTestState extends State<IsolateTest> {
  int _count = 0;

  //耗时工作,计算偶数个数
  static int calculateEvenCount(int num) {
    int count = 0;
    while (num > 0) {
      if (num % 2 == 0) {
        count++;
      }
      num--;
    }
    return count;
  }

  //模拟Future耗时
  void doMockTimeConsume() async {
    // 调用无参数的任务
    ThreadManagement.runTask<int>(getParamsTask, (value) {
      _count = value;
      if (mounted) {
        setState(() {});
      }
    }, parameter: 1000000000);
  }

  // 需要参数的任务
  static getParamsTask(SendPort port) async {
    ReceivePort receivePort = ReceivePort();
    port.send(receivePort.sendPort);
    // 监听外界调用
    await for (var msg in receivePort) {
      int n = msg[0];
      SendPort callbackPort = msg[1];
      receivePort.close();
      int res = calculateEvenCount(n);
      callbackPort.send(res);
    }
  }

  // // 无参数的任务,例子
  // static void getNoParamTask(SendPort port) async {
  //   var c = await Future.delayed(Duration(seconds: 1), () {
  //     return "banner data";
  //   });
  //   port.send(c);
  // }


  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 100,
            height: 100,
            child: CircularProgressIndicator(),
          ),
          Text(_count.toString()),
          TextButton(
            onPressed: () {
              //触发耗时操作
              doMockTimeConsume();
            },
            child: Text('开始耗时工作[另开线程]'),
          ),
          TextButton(
            onPressed: () {
              //触发耗时操作
              _count = calculateEvenCount(1000000000);
              setState(() {});
            },
            child: Text('开始耗时工作[在主线程]'),
          )
        ],
      ),
    );
  }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值