Flutter中如何取消任务
Posted 编程黑板报
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter中如何取消任务相关的知识,希望对你有一定的参考价值。
前言
在开发过程中,取消需求是很常见的,但很容易被忽略。然而,取消需求的好处也很大。例如,在页面中会发送很多请求。如果页面被切走并处于不可见状态,就需要取消未完成的请求任务。如果未及时取消,则可能会导致以下负面影响:
- 消耗用户额外数据流量。
- 任务回调持有全局上下文变量,未及时释放存在内存泄漏风险
- 异步请求过多消耗大量系统资源,拖慢 UI 线程,造成卡顿。
在 Flutter 中,如何取消已经在进行的任务呢?首先需要掌握一些基础知识。
前置知识
Future#any 方法
传入一个 Future 任务列表,返回第一个完成的异步任务,无论成功或失败。
定义
用法
如下 5 个异步任务,代码第五行虽然第二执行,但是最先执行完毕,所以第一个返回,至此整个 Future.any 函数执行完毕。
结果输入如下:
总结
- Future.any 实际就是一个 Completer,N 个 Future 叠加在一起,谁先完成算谁的。
- Future.any 可以理解成百米赛跑,其中每个选手就是一个 Future,谁跑最快到终点谁就赢了。
Dio 取消实现解析
dio 版本
dio: dev v5.0.3
git: 67f07b86a0976c14a6e19061563832d92ed6772b
branch: main
如何取消
请求中传入 CancelToken 对象,然后调用 token.cancel 方法即可
final cancelToken = CancelToken();
dio.get(url, cancelToken: cancelToken).catchError((DioError err)
if (CancelToken.isCancel(err))
print(\'Request canceled: $err.message\');
else
// handle error.
);
// Cancel the requests with "cancelled" message.
token.cancel(\'cancelled\');
流程解析
思路:在实际任务执行前使用 Future.any 函数插入取消任务。如果实际任务没有执行完,就有机会取消它。
如下代码,黄色标注按照步骤来读就行。
总结:CancelToken 就像一个渣男,而 Future.any 则提供了公平竞争的机会。只要妹子还没有交男朋友,渣男就有机会中途得手。
说明
取消任务不仅限于网络请求。任何实际业务中包含不必要的耗时操作都可以通过 Future.any 配合 CancelToken 来实现取消。
Flutter Firebase Cloud Messaging 如何自动关闭/取消通知?
【中文标题】Flutter Firebase Cloud Messaging 如何自动关闭/取消通知?【英文标题】:Flutter Firebase Cloud Messaging how to Auto Dismiss/Cancel a notification? 【发布时间】:2022-01-17 18:52:02 【问题描述】:我已经成功地通过控制台以及从我的 NodeJs 服务器接收 FCM 消息(在我的手机上)。但是我如何发送和接收将到达我的手机的 FCM 消息,执行一些任务,然后自行自动取消/关闭?
这在 Flutter with FCM 中是否可行?
在Android中,我们曾经有public Notification.Builder setTimeoutAfter (long durationMs)
更多的是用于 ping 客户端应用程序...并从应用程序本地存储中检索一些数据。因为它可以自动完成,所以我想这样做而不会给用户带来麻烦。
【问题讨论】:
为什么不使用 Job Scheduler?要ping(智能手机应用程序是否存在)或读取本地数据,您可以使用Job Scheduler ios:backgroudbatch。 用户似乎在使用外部系统,例如 cronjob 服务器。 是的,这是真的。我们想使用像 CronJob 这样的外部服务。我们不需要像 JobScheduler 或 Background Fetch 这样的背景检查。 【参考方案1】:这些是完成以下步骤的步骤
在不打扰用户的情况下接收通知(在系统托盘中没有任何警报的静默方式) 让 localNotification Pkg 启动进度通知 执行后台任务并完成后 通过 LocalNotifications Pkg 取消通知确保您的 .yaml 文件中包含以下内容...在解决此问题时,我有以下版本:
firebase_messaging: ^11.1.0 firebase_core: ^1.10.0 flutter_local_notifications: ^9.1.
对于本地通知包,让我们创建一个类来使用它的服务
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class LocalNotificationService
static final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();
static void initialize(BuildContext context)
final InitializationSettings initializationSettings = InitializationSettings(
android: const AndroidInitializationSettings("@mipmap/your_icon"));
_notificationsPlugin.initialize(initializationSettings);
//=================================================
//==============this is the update notification
static Future<void> showProgressNotification() async
const int maxProgress = 5;
for (int i = 0; i <= maxProgress; i++)
await Future<void>.delayed(const Duration(seconds: 1), () async
final AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails('progress channel', 'progress channel',
channelDescription: 'progress channel description',
channelShowBadge: false,
importance: Importance.max,
priority: Priority.high,
playSound: false,
showProgress: true,
maxProgress: maxProgress,
progress: i);
final NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await _notificationsPlugin.show(
0,//I use this id to cancel it from below method
'progress notification title',
'progress notification body',
platformChannelSpecifics,
payload: 'item x');
);
//=========================and this is for the ProgressNotification to be cancelled
static Future<void> cancelNotification() async
await _notificationsPlugin.cancel(0);
//end of class
让你在你的Widget的init方法中初始化它
@override
void initState()
// TODO: implement initState
super.initState();
LocalNotificationService.initialize(context);
最后...这是您的 Main() 和***处理程序的外观
//Receive message when app is in background/minimized
//THIS IS THE TOP LEVEL HANDLER.. as it is outside the scope of main()
Future<void> backgroundHandler(RemoteMessage message) async
print("from the Background Handler Top Function()..............");
print(message.data.toString());
//now for the localNotification to take over
await LocalNotificationService.showProgressNotification();
await Future<void>.delayed(const Duration(seconds: 2));//faking task delay
await LocalNotificationService.cancelNotification();//by default I have made id=0
void main() async
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(backgroundHandler);//this has to be a TOP LEVEL METHOD
runApp(MyApp());
在服务器端发送通知时确保只有数据...见@Junsu Cho 回答
【讨论】:
【参考方案2】:ios 是不可能的 android 是可能的,删除通知负载
"to": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
"notification":
"title": "title"
"data":
"data" : "data"
到
"to": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
"data":
"data" : "data"
【讨论】:
是的,我们确实尝试过...这不会使通知出现在系统托盘中...但我们希望通知出现,让任务完成...然后自行取消。这才是真正的问题……有什么想法吗? 由于 fcm 是一种单向协议,因此无法自动关闭。我的想法是使用 fcm 推送运行服务,使用服务结束任务,然后终止服务。 是的,回到这里我们也开始这么想了。所以让我们给它几天时间,否则我们会接受你的建议。以上是关于Flutter中如何取消任务的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Flutter 中完全取消对 TextField 的关注,而无需稍后返回焦点