英文:
Anonymous functions and callbacks...why doesn't work?
问题
需要在Flutter中将参数传递给回调函数。
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), alarmCallback); // 正常工作
回调函数如下:
void alarmCallback(String id){
print("Hello, " + id);
}
我使用匿名函数方式传递参数,但它不起作用,回调函数不会执行:
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), () => alarmCallback(id)); // 不起作用
我尝试以这种方式传递参数,但它不起作用,回调函数不会执行。当我把光标放在id上时,IDE显示它是动态的,但它是字符串:
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), (id) => alarmCallback(id)); // 不起作用
提前感谢!
英文:
I need to pass a parameter to a callback in Flutter.
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), alarmCallback); //WORKS
The callback is:
void alarmCallback(String id){
print("Hello, " + id);
}
I pass the parameter using anonymous function way, but it doesn't work, the callback isn't executed:
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), () => alarmCallback(id)); //DOESN'T WORK
I pass the parameter in this way, but it doesn't work, the callback isn't executed, when I put my cursor on id the IDE shows me that it's dynamic, but it's string:
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), (id) => alarmCallback(id)); //DOESN'T WORK
Thx in advance!
答案1
得分: 2
以下是翻译好的部分:
我写了一个简短的示例。此代码注册了定期闹钟和一次性闹钟。回调函数以int
作为参数。
请注意,自API 19(Build.VERSION_CODES.KITKAT)起,闹钟传递是不精确的。
查看:
https://stackoverflow.com/a/56012077/2632894
https://developer.android.com/reference/android/app/AlarmManager
我正在运行以下版本的Flutter和Dart:
Flutter 1.13.7-pre.31 • 通道 master • https://github.com/flutter/flutter.git
Framework • 修订版 ee7a37f1d3(4小时前) • 2020年01月07日 00:00:00 -0000
引擎 • 修订版 3851981b86
工具 • Dart 2.8.0(构建 2.8.0-dev.0.0 2f57602411)
android_alarm_manager: ^0.4.5+2
main.dart
import 'package:flutter/material.dart';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'dart:isolate';
void callbackFunction(int id) async {
final DateTime now = DateTime.now();
final int isolateId = Isolate.current.hashCode;
print('[$now] Param=$id isolate=$isolateId function=$callbackFunction');
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
AndroidAlarmManager.initialize();
runApp(MyApp());
final int alarmID = 42;
await AndroidAlarmManager.periodic(const Duration(minutes: 1), alarmID,
callbackFunction, wakeup: true, exact: true, rescheduleOnReboot:true).then((val) => print('periodic alarm set up:' + val.toString()));
final int anotherAlarmID = 666;
AndroidAlarmManager.oneShot(
Duration(seconds: 3),
anotherAlarmID,
callbackFunction,
wakeup: true,
).then((val) => print('oneShot alarm set up:' + val.toString()));
}
...
...
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="at.full.flutter_app_new">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_app_new"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="io.flutter.plugins.androidalarmmanager.AlarmService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<receiver
android:name="io.flutter.plugins.androidalarmmanager.AlarmBroadcastReceiver"
android:exported="false"/>
<receiver
android:name="io.flutter.plugins.androidalarmmanager.RebootBroadcastReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
输出应与以下示例类似:
I/FlutterBackgroundExecutor(12111): Starting AlarmService...
I/AndroidAlarmManagerPlugin(12111): onAttachedToEngine
I/flutter (12111): periodic alarm set up:true
I/flutter (12111): oneShot alarm set up:true
I/AlarmService(12111): AlarmService started!
I/flutter (12111): [2020-01-07 00:05:33.065838] Param=666! isolate=470178969 function='Closure: (int) => void from Function 'callbackFunction': static.'
I/flutter (12111): [2020-01-07 00:06:26.158709] Param=42! isolate=470178969 function='Closure: (int) => void from Function 'callbackFunction': static.'
英文:
I wrote a short example. This code registers a periodic alarm + a one time alarm. The callback function takes an int
as parameter.
Keep in mind that since API 19 (Build.VERSION_CODES.KITKAT) alarm delivery is inexact
See:<br>
https://stackoverflow.com/a/56012077/2632894
https://developer.android.com/reference/android/app/AlarmManager
I'm running the following versions of Flutter and Dart:
Flutter 1.13.7-pre.31 • channel master • https://github.com/flutter/flutter.git
Framework • revision ee7a37f1d3 (4 hours ago) • 2020-01-07 00:00:00 -0000
Engine • revision 3851981b86
Tools • Dart 2.8.0 (build 2.8.0-dev.0.0 2f57602411)
android_alarm_manager: ^0.4.5+2
main.dart
<!-- language: lang-dart -->
import 'package:flutter/material.dart';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'dart:isolate';
void callbackFunction(int id) async {
final DateTime now = DateTime.now();
final int isolateId = Isolate.current.hashCode;
print('[$now] Param=$id isolate=$isolateId function=$callbackFunction');
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
AndroidAlarmManager.initialize();
runApp(MyApp());
final int alarmID = 42;
await AndroidAlarmManager.periodic(const Duration(minutes: 1), alarmID,
callbackFunction, wakeup: true, exact: true, rescheduleOnReboot:true).then((val) => print('periodic alarm set up:' + val.toString()));
final int anotherAlarmID = 666;
AndroidAlarmManager.oneShot(
Duration(seconds: 3),
anotherAlarmID,
callbackFunction,
wakeup: true,
).then((val) => print('oneShot alarm set up:' + val.toString()));
}
...
...
AndroidManifest.xml
<!-- language: lang-xml-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="at.full.flutter_app_new">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_app_new"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="io.flutter.plugins.androidalarmmanager.AlarmService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<receiver
android:name="io.flutter.plugins.androidalarmmanager.AlarmBroadcastReceiver"
android:exported="false"/>
<receiver
android:name="io.flutter.plugins.androidalarmmanager.RebootBroadcastReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
The Ouptut should be similar to this one:
I/FlutterBackgroundExecutor(12111): Starting AlarmService...
I/AndroidAlarmManagerPlugin(12111): onAttachedToEngine
I/flutter (12111): periodic alarm set up:true
I/flutter (12111): oneShot alarm set up:true
I/AlarmService(12111): AlarmService started!
I/flutter (12111): [2020-01-07 00:05:33.065838] Param=666! isolate=470178969 function='Closure: (int) => void from Function 'callbackFunction': static.'
I/flutter (12111): [2020-01-07 00:06:26.158709] Param=42! isolate=470178969 function='Closure: (int) => void from Function 'callbackFunction': static.'
答案2
得分: 1
箭头函数语法如下:
(params) => function(params)
等同于:
Type some_name(params){
return function(params)
}
回调可以是Function()或Function(int)
如果它是Function(int)类型,id将传递给回调函数
因此,可以有id也可以没有,但此id必须是int类型。
由于你不太关心函数的返回值,你可以直接传递一个函数:
(int id){print("Hello, " + id);}
这不会返回任何内容。
在你的调用中,应该是这样的:
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), (int id){alarmCallback(id);});
英文:
The fat arrow syntax is like the following:
(params) => function(params)
is the same as :
type some_name(params){
return function(params)
}
From the documentation of oneShotAt method:
> callback can be Function() or Function(int)
>
> id will passed to callback if it is of type Function(int)
So it may be with or without id, and this id must be a int.
Since you are not worried so much about the return of the function, you can pass a function directly:
(int id){print("Hello, " + id);}
which won't return anything.
In your call, it should be like:
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), (int id){alarmCallback(id);});
答案3
得分: 0
I don't know what log errors you got but try this:
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), (id) => alarmCallback(id));
英文:
i don't know what log errors you got but try this:
AndroidAlarmManager.oneShotAt(DateTime.now().add(Duration(seconds: 5)), int.parse(id), (id) => alarmCallback(id));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论