我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Flutter 队列任务的实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Flutter 队列任务的实现

前言

在电商的应用中,最常见的就是在首页或完成某事件之后,弹出一堆的活动/广告。假如重叠弹出,很丑,给用户的体验也不好,所以一般都会依次依条件的弹出。

下面讲讲我是怎么实现一个方便的队列任务管理

队列

任务队列,那当然要有个队列。这个队列的任务内容应该是返回FutureFunction,因为我需要得到他处理完成的结果,比如等待弹窗关闭时return,才表示这个任务被完成。

typedef TaskEventFunction = Future Function();

class TaskQueue {
    List<TaskEventFunction> _actionQueue = [];
}

添加任务进队列

然后是加入队列的方法add

void add(TaskEventFunction task) {
  _actionQueue.add(task);
}

然后想到,队列是不是最好去重?或者可选去重。

那一个Function如何去重呢,我们可以使用它的hashCode,同一个FunctionhashCode相同

taskQueue.add(testFunction);

Future testFunction() async {
  await Future.delayed(const Duration(milliseconds: 1000));
  return Future.value(true);
}

即我们可以按上面这样定义,同一个类同一个实例下同一个Function,就是相同的hashCode。若是以下这种写法则hashCode不一样,每次add都相当于一个新的Function

taskQueue.add(() async {
  await Future.delayed(const Duration(milliseconds: 1000));
  return Future.value(true);
});

假如不需要去重,可以用第二种。也可以主动指定taskId来选择哪些需要去重(即使内容不一样),哪些不需要。

修改一下add,增加taskId。同时hashCode应该作为主要的key,修改一下队列类型。 最终如下:

/// 任务编号队列
List<String> _actionQueue = [];

/// 任务队列
Map<String, TaskEventFunction> _actionMap = {};

/// 指定taskId 为 -1 则不用去重
String add(TaskEventFunction task, {
  String? taskId,
}) {
  String? id = taskId;
  id ??= task.hashCode.toString();
  bool isContains = false;
  if (taskId != '-1') {
    isContains = _actionQueue.contains(id);
  } else {
    id = task.hashCode.toString();
  }
  if (!isContains) {
    _actionQueue.add(id);
    _actionMap[id] = task;
  }
  return id;
}

-1时则不去重,也把最终的taskId返回。

移除队列指定任务

有添加任务的方法,那也需有移除任务的方法

/// 这里需注意,add的时taskId为-1,那就直接把task传入,add时有返回,可以对应
bool remove(TaskEventFunction task, {String? taskId}) {
  String? id = taskId;
  id ??= task.hashCode.toString();
  if (_actionQueue.contains(id)) {
    _actionMap.remove(id);
    return _actionQueue.remove(id);
  }
  return false;
}

taskId/hashCode为准。

判断是否包含对应任务

使用者可以自己判断是否已包含对应的任务

/// 是否队列中包含该任务
/// [task] 与 [taskId] 应该只传一个
bool containers({TaskEventFunction? task, String? taskId}) {
  assert(task != null || taskId != null);
  String? id = taskId;
  id ??= task.hashCode.toString();
  return _actionQueue.contains(taskId);
}

执行队列任务

任务队列的进出基本成型,开始处理任务。很简单,取出任务,然后执行任务,最后移除任务

void startLoop() async {
  if (dealing || _actionQueue.isEmpty) {
    return;
  }
  dealing = true;
  String taskId = _actionQueue.first;
  TaskEventFunction? callback = _actionMap[taskId];
  if (callback == null) {
    _actionQueue.remove(taskId);
    return;
  }

  try {
    await callback();
  } catch (e) {
    log('_actionQueue 出错 $e');
  } finally {
    _actionQueue.remove(taskId);
    _actionMap.remove(taskId);
    dealing = false;
    if (_actionQueue.isNotEmpty) {
      startLoop();
    }
  }
}

这里加了个dealing,表示任务正在处理中的状态,正在处理的话,不允许执行下一个任务。

在执行完成(或失败)后,自动触发下一个任务。add中也可以加入startLoop,使添加任务后自动启动任务循环。

任务条件

基本的任务队列已经完成。不过每个任务其实一般都会有个条件,确认符合当前场景才执行。比如说的确是新人且在首页,才显示新人优惠弹窗。

条件可以是整个任务队列统一的条件,也可以是某个任务特定的条件

typedef TaskConditionFunction = FutureOr<bool> Function();

这里类型用FutureOr<bool>,有可能需要等待一下才能确认条件。任务对应的条件,也根据taskId来存储。

/// 任务条件
Map<String, TaskConditionFunction> _actionCondition = {};

/// 总条件
TaskConditionFunction? _condition;

添加任务时加入条件

TaskEventFunction add(TaskEventFunction task, {
  String? taskId,
  TaskConditionFunction? condition,
}) {
    ...
    
    if (condition != null && !_actionCondition.containsKey(id)) {
      _actionCondition[id] = condition;
    }

}

设置总条件,或补充条件

/// 设置允许执行条件
void setAcceptConditions(TaskConditionFunction condition,
    {String? taskId}) {
  if (taskId == null) {
    _condition = condition;
  } else {
    _actionCondition[taskId] = condition;
  }
}

执行任务前判断条件是否满足

    bool canNext = await _nextConditions(taskId);
    if (canNext) {
      try {
        await callback();
      } catch (e) {
        log('_actionQueue 出错 $e');
      } finally {
        _actionQueue.remove(taskId);
        _actionMap.remove(taskId);
        dealing = false;
        if (_actionQueue.isNotEmpty) {
          startLoop();
        }
      }
    } else {
      // 不满足条件一般后续的也不会执行
      dealing = false;
    }
Future<bool> _nextConditions([String? id]) async {
  String taskId = id ?? _actionQueue.first;
  bool canNext = true;
  var taskCondition = _actionCondition[taskId];
  if (_condition != null) {
    canNext = await _condition!.call();
  }
  if (canNext && taskCondition != null) {
    canNext = await taskCondition();
  }

  return Future.value(canNext);
}

原则上应该既满足总条件也满足任务条件

使用和总结

实例化TaskQueue

TaskQueue taskQueue = TaskQueue();

添加任务并开始任务

taskQueue.add(testFunction, condition: () async {
  await Future.delayed(const Duration(milliseconds: 200));
  return Future.value(true);
});
taskQueue.startLoop();

Future testFunction() async {
  return showDialog(...);
}

注意设置条件要返回bool

还可以加入类似延时等操作,跟条件一样配置即可。太久的操作不要像上面一样写在condition中,可能执行完之后又不满足了,根据具体情况考虑。

一般来说类似弹窗的returnawait showDialog就可以等待弹窗页面结束,再进行下一个。

跨页面还是当前页面的控制,只需要考虑是全局实例TaskQueue还是页面内实例TaskQueue

这样一个使用简单好用的任务队列就实现好了,更多相关Flutter 队列任务内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Flutter 队列任务的实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Flutter队列任务如何实现

本篇内容介绍了“Flutter队列任务如何实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!队列任务队列,那当然要有个队列。这个队列的任务内
2023-07-02

Node.js + Redis Sorted Set实现任务队列

需求:功能 A 需要调用第三方 API 获取数据,而第三方 API 自身是异步处理方式,在调用后会返回数据与状态 { data: "查询结果", "status": "正在异步处理中" } ,这样就需要间隔一段时间后再去调用第三方 API
2022-06-04

golang异步任务队列怎么实现

在Go语言中,可以使用goroutine和channel来实现异步任务队列。下面是一个简单的示例代码:package mainimport ("fmt""sync""time")func main() {// 创建一个无缓冲的chann
2023-10-27

vue中的任务队列和异步更新策略(任务队列,微任务,宏任务)

这篇文章主要介绍了vue中的任务队列和异步更新策略(任务队列,微任务,宏任务),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-11-13

Python实现简单多线程任务队列

最近我在用梯度下降算法绘制神经网络的数据时,遇到了一些算法性能的问题。梯度下降算法的代码如下(伪代码):def gradient_descent():# the gradient descent codeplotly.write(X, Y)
2022-06-04

Laravel怎么实现队列和任务调度

本文小编为大家详细介绍“Laravel怎么实现队列和任务调度”,内容详细,步骤清晰,细节处理妥当,希望这篇“Laravel怎么实现队列和任务调度”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、 我们首先准备一下
2023-07-04

RabbitMQ消息队列怎么实现延迟任务

这篇文章主要介绍“RabbitMQ消息队列怎么实现延迟任务”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“RabbitMQ消息队列怎么实现延迟任务”文章能帮助大家解决问题。一、序言延迟任务应用广泛,延
2023-06-29

如何在Redis中实现延迟任务队列

在Redis中实现延迟任务队列可以使用有序集合(Sorted Set)和定时任务的方式来实现。以下是一个基本的实现方法:将任务存储在一个有序集合中,按照任务的执行时间作为分数(score),任务的内容作为值(value)来存储。例如,使用Z
如何在Redis中实现延迟任务队列
2024-04-09

laravel6中怎么实现队列与任务调度

本篇文章为大家展示了laravel6中怎么实现队列与任务调度,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。(一)队列实现在laravel中,队列的实现我们只需要通过操作,就能实现,在实现的前提,我们
2023-06-20

如何用Go语言和Redis实现任务队列

如何用Go语言和Redis实现任务队列引言:在实际的软件开发中,经常会遇到需要处理大量任务的场景。为了提高处理效率和可靠性,我们可以使用任务队列来分发和执行这些任务。本文将介绍如何使用Go语言和Redis实现一个简单的任务队列,以及具体的代
2023-10-26

如何利用Redis实现分布式任务队列

如何利用Redis实现分布式任务队列引言:随着互联网应用的快速发展,分布式系统成为了企业追求高性能和高可扩展性的重要选择。而在分布式系统中,任务队列被广泛应用于各种场景,例如消息发布、数据同步、任务调度等。Redis作为一款快速的内存数据库
如何利用Redis实现分布式任务队列
2023-11-07

Redis数据库队列怎么实现异步任务

在Redis中实现异步任务可以通过Redis的列表数据结构来实现队列。下面是一种常见的实现方式:生产者将需要执行的任务加入到Redis列表中,例如将任务数据作为消息推送到队列中。消费者从Redis列表中获取任务并执行,处理完任务后将结果存
Redis数据库队列怎么实现异步任务
2024-04-22

Golang中使用RabbitMQ实现任务队列的优化技巧

在Golang中使用RabbitMQ实现任务队列时,可以使用以下技巧进行优化:1. 使用消息确认机制:在消费者处理完任务后,手动确认消息的消费完成。这可以确保消息被正确处理,避免重复消费或丢失消息。2. 设置预取计数:使用`channel.
2023-10-08

队列在PHP与MySQL中的任务监控和任务调度的实现方案

引言在现代的Web应用程序开发中,任务队列是非常重要的一项技术。通过队列,我们可以将一些需要在后台执行的任务排队,并通过任务调度来控制任务的执行时间和顺序。本文将介绍如何在PHP与MySQL中实现任务的监控和调度,并提供具体的代码示例。一、
2023-10-21

基于Redis实现分布式锁以及任务队列

一、前言双十一刚过不久,大家都知道在天猫、京东、苏宁等等电商网站上有很多秒杀活动,例如在某一个时刻抢购一个原价1999现在秒杀价只要999的手机时,会迎来一个用户请求的高峰期,可能会有几十万几百万的并发量,来抢这个手机,在高并发的情形下会对
2022-06-04

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录