匿名函数和回调…为什么不起作用?

huangapple go评论83阅读模式
英文:

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 &#39;package:flutter/material.dart&#39;;
import &#39;package:android_alarm_manager/android_alarm_manager.dart&#39;;
import &#39;dart:isolate&#39;;

void callbackFunction(int id) async {
  final DateTime now = DateTime.now();
  final int isolateId = Isolate.current.hashCode;
  print(&#39;[$now] Param=$id isolate=$isolateId function=$callbackFunction&#39;);
}

Future&lt;void&gt; 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) =&gt; print(&#39;periodic alarm set up:&#39; + val.toString()));

  final int anotherAlarmID = 666;
  AndroidAlarmManager.oneShot(
    Duration(seconds: 3),
    anotherAlarmID,
    callbackFunction,
    wakeup: true,
  ).then((val) =&gt; print(&#39;oneShot alarm set up:&#39; + val.toString()));

}
...
...

AndroidManifest.xml
<!-- language: lang-xml-->

&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    package=&quot;at.full.flutter_app_new&quot;&gt;

    &lt;uses-permission android:name=&quot;android.permission.RECEIVE_BOOT_COMPLETED&quot;/&gt;
    &lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot;/&gt;

    &lt;application
        android:name=&quot;io.flutter.app.FlutterApplication&quot;
        android:label=&quot;flutter_app_new&quot;
        android:icon=&quot;@mipmap/ic_launcher&quot;&gt;
        &lt;activity
            android:name=&quot;.MainActivity&quot;
            android:launchMode=&quot;singleTop&quot;
            android:theme=&quot;@style/LaunchTheme&quot;
            android:configChanges=&quot;orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode&quot;
            android:hardwareAccelerated=&quot;true&quot;
            android:windowSoftInputMode=&quot;adjustResize&quot;&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=&quot;android.intent.action.MAIN&quot;/&gt;
                &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot;/&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;

        &lt;service
            android:name=&quot;io.flutter.plugins.androidalarmmanager.AlarmService&quot;
            android:permission=&quot;android.permission.BIND_JOB_SERVICE&quot;
            android:exported=&quot;false&quot;/&gt;
        &lt;receiver
            android:name=&quot;io.flutter.plugins.androidalarmmanager.AlarmBroadcastReceiver&quot;
            android:exported=&quot;false&quot;/&gt;
        &lt;receiver
            android:name=&quot;io.flutter.plugins.androidalarmmanager.RebootBroadcastReceiver&quot;
            android:enabled=&quot;false&quot;&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=&quot;android.intent.action.BOOT_COMPLETED&quot;/&gt;
            &lt;/intent-filter&gt;
        &lt;/receiver&gt;

        &lt;meta-data
            android:name=&quot;flutterEmbedding&quot;
            android:value=&quot;2&quot; /&gt;
    &lt;/application&gt;
&lt;/manifest&gt;

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=&#39;Closure: (int) =&gt; void from Function &#39;callbackFunction&#39;: static.&#39;
I/flutter (12111): [2020-01-07 00:06:26.158709] Param=42! isolate=470178969 function=&#39;Closure: (int) =&gt; void from Function &#39;callbackFunction&#39;: static.&#39;

答案2

得分: 1

箭头函数语法如下:

(params) => function(params)

等同于:

Type some_name(params){
    return function(params)
}

来自oneShotAt方法的文档

回调可以是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) =&gt; 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(&quot;Hello, &quot; + 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) =&gt; alarmCallback(id));

huangapple
  • 本文由 发表于 2020年1月7日 01:46:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/59616641.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定