Benachrichtigung & Alarme im Flattern
Arbeiten mit dem Flutter Plugin, Android_Alarm_Manager.
Wisse das! Dieses Plugin funktioniert nur für die Android- Plattform! Ich persönlich kenne kein iOS-Äquivalent. Alternativ stieß ich einen Monat nach Veröffentlichung dieses Artikels auf ein Plugin, das Benachrichtigungen sowohl auf der Android- als auch auf der iOS-Plattform bereitstellt. Ich habe natürlich einen Artikel geschrieben und das auch. Siehe unten.
Wenn Sie das hier beschriebene Plugin verwenden möchten, müssen Sie dessen Readme- Datei explizit folgen, um die Einstellungen korrekt vorzunehmen. Ihre AndroidManfest.xml sollte mindestens so aussehen:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="NAME OF YOUR APPLICATION STARTING WITH COM.">
<!-- The INTERNET permission access.-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- android_alarm_manager -->
<!-- Start an Alarm When the Device Boots if past due -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- application needs to have the device stay on -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:name="io.flutter.app.FlutterApplication"
android:label="code_samples"
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">
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- android_alarm_manager -->
<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>
</application>
</manifest>
# https://pub.dev/packages/android_alarm_manager
android_alarm_manager: ^0.4.0
In diesem Fall dient es zum Auslösen von Alarmen in Ihrer App! In meinem Fall habe ich festgestellt, dass das Flutter-Plugin android_alarm_manager die Anforderungen einer aktuellen App erfüllt, an der ich gearbeitet habe, und so… habe ich eine Routine erstellt, um einfach damit zu arbeiten. Wenn Sie es möchten, nehmen Sie eine Kopie , machen Sie es sich selbst und teilen Sie alle Verbesserungen, die Sie vornehmen. Cool?
Wenn Sie Zeit haben, lesen Sie bitte weiter, was ich tun musste, damit dieses Plugin fast "kinderleicht" funktioniert, damit Sie einfach und schnell einen Alarm oder eine andere Operation einstellen können, die irgendwann "im Hintergrund" ausgeführt werden soll rechtzeitig in der Zukunft, während die App läuft. Es macht das Leben ein bisschen einfacher, und das ist gut so. Richtig?
Nur Screenshots. Klicken Sie auf Für Listen.
Wie immer bevorzuge ich Screenshots gegenüber Gists, um Code in meinen Artikeln anzuzeigen. Ich finde sie leichter zu bearbeiten und leichter zu lesen. Sie können jedoch darauf klicken / tippen, um den Code in einer Übersicht oder in Github anzuzeigen. Ironischerweise ist es besser, diesen Artikel über die mobile Entwicklung auf Ihrem Computer zu lesen als auf Ihrem Telefon. Außerdem programmieren wir hauptsächlich auf unseren Computern; nicht auf unseren Handys. Zur Zeit.
Lass uns anfangen.
Mein Ansatz hier ist es, diese Dienstprogrammklasse zunächst in einem Beispiel vorzustellen und ihre Verwendung zu demonstrieren - und dabei das Flutter-Plugin android_alarm_manager zu nutzen . Tatsächlich werde ich das gleiche Beispiel verwenden, das auf der eigenen Beispielseite des Plugins aufgeführt ist . Dieses Beispiel wurde jedoch geändert, um stattdessen die hier dargestellte Bibliotheksdatei zu verwenden. Eine Kopie dieses Beispiels steht Ihnen als Kern android_alarm_manager zur Verfügung . Nach dem Beispiel gehe ich durch Teile der Utility-Klasse selbst und beschreibe zuweilen, was getan werden muss, damit eine solche Klasse von den unnachgiebigen Massen der allgemeinen Öffentlichkeit verwendet werden kann.
Halten Sie es statisch
In diesem sehr einfachen Beispiel müssen Sie die angezeigte Taste drücken, und 5 Sekunden später werden diese beiden Nullen, wie im folgenden Screenshot dargestellt, zu Einsen. Wheeee! Was wirklich interessant ist, ist natürlich, was sich im Code unter der Haube befindet.
Hinweis: Ich habe den Code vom Original geändert, um die asynchronen Vorgänge zu berücksichtigen, die ausgeführt werden müssen, bevor die App tatsächlich ausgeführt werden kann. Ich habe ein FutureBuilder-Widget verwendet, um dies zu erreichen. Dabei habe ich eine neue Funktion namens initSettings () definiert , um die Routine "Gemeinsame Einstellungen" zu initialisieren, mit der die Anzahl der insgesamt ausgelösten Alarme gespeichert wird (siehe Abbildung oben).
Sie können auch in der unten angezeigten Funktion initSettings () sehen, dass die Gesamtanzahl auf Null gesetzt wird, wenn die App zum ersten Mal ausgeführt wird. Zu Beginn wird jedoch die Bibliotheksroutine AlarmManager initialisiert, um den speziellen Alarmdienst einzurichten, der zum Ausführen von Benachrichtigungen auf einem Android-Telefon erforderlich ist.
Lassen Sie uns den Beispielcode weiter unten durchgehen und sehen, was diese kleine Schaltfläche ausmacht. Beachten Sie, dass die Bibliotheksroutine dieselben Namen für die Parameter und Funktionen verwendet, aus denen das unterstrichene Flutter-Plugin Android_Alarm_Manager besteht . Besser mit solchen Dingen im Einklang zu sein. Ähnlich wie bei der oneShot () -Funktion des Plugins wartet die einmal aufgerufene Version dieser Bibliothek auf die angegebene Dauer, bevor die angegebene Rückrufroutine ausgelöst wird. In diesem modifizierten Beispiel ist die Rückrufroutine eine anonyme Funktion, die nach einer Dauer von 5 Sekunden ausgeführt wird. Im folgenden Screenshot wurde die App tatsächlich neu gestartet. Die Schaltfläche wurde erneut gedrückt, was dank der freigegebenen Einstellungen anzeigt, dass die Schaltfläche seit ihrer ersten Ausführung zweimal gedrückt wurde. Wheeee.
Ein genauerer Blick auf diese anonyme Funktion unten zeigt, dass ein einzelner Parameter vom Typ Integer übergeben wird. Mit den Dart-Funktionen Random (). NextInt (pow (2,31)) können Sie davon ausgehen, dass dies derselbe ID-Wert ist, der als Zufallszahl an den zweiten Parameter übergeben wird . Warum sollte man sich nun die Mühe machen, diesen Wert zu übergeben, wenn er bereits an den Parameter direkt daneben übergeben wurde? Wir werden dazu kommen.
Im Moment können Sie weiter unten sehen, dass die Rückruffunktion wiederum die Funktion _incrementCounter () aufruft . Dort wird die aktuelle "Gesamtzahl" der Tastendrücke aus der Routine "Gemeinsame Einstellungen" abgerufen. Es wird dann um eins aktualisiert, um diesen aktuellen Tastendruck zu berücksichtigen, und in den freigegebenen Einstellungen gespeichert. Der Bildschirm der App wird dann mit der inkrementierten Variablen _counter mithilfe der Funktion setState () aktualisiert . Hast du das alles bisher verfolgt?
Statisch halten
Im Gegensatz zum ursprünglichen Beispiel (siehe unten) darf in diesem Beispiel eine anonyme Funktion verwendet werden, ohne dass eine statische Funktion speziell verwendet werden muss. Natürlich dürfen Sie auch in diesem Beispiel eine statische Funktion verwenden - solange dieser einzelne ganzzahlige Wert noch akzeptiert wird. Im ursprünglichen Beispiel muss es sich jedoch um eine statische Funktion oder eine übergeordnete Funktion handeln, die außerhalb einer Klasse in dieser Dart-Bibliotheksdatei definiert ist. Eine davon ist eine Voraussetzung, wenn Sie direkt mit dem Flutter-Plugin Android_Alarm_Manager arbeiten .
Wenn Sie jedoch meinen Artikeln gefolgt sind, wissen Sie, dass mir Optionen gefallen. Es geht darum, Optionen bei mir zu haben. Ich habe diese Utility-Klasse so geschrieben, dass sie entgegenkommender ist - zum Beispiel um anonyme Funktionen zu ermöglichen. Wenn bei einer solchen Anordnung dieser ganzzahlige ID-Wert als Parameter übergeben wird, kann die Funktion tatsächlich eine statische Funktion, eine Funktion auf hoher Ebene oder eine anonyme Funktion sein. Optionen! Wiederum folgen Screenshots des ursprünglichen Beispiels:
Wenden wir uns der Utility-Klasse AlarmManager selbst zu. Auch hier ist es so konzipiert, dass es mit dem Plugin funktioniert. Und wieder sind es viele Parameter, die vom Plugin verwendet werden und daher an dieses Plugin übergeben werden - jedoch nicht vor einigen umfangreichen Parametertests auf gültige Werte. Ein weiteres notwendiges Merkmal solcher Gebrauchsklassen. Es macht die ganze Arbeit, so dass Sie nicht müssen. Richtig?
In der Abbildung unten sehen Sie den ersten Teil dieser Dienstprogrammklasse. In seiner statischen Funktion init () sehen wir, dass das Plugin tatsächlich initialisiert ist. Beachten Sie, dass alle unglücklichen Fehler, die beim Initialisierungsversuch auftreten können, in der try-catch- Anweisung abgefangen werden . Utility-Klassen müssen das auch tun. Als nächstes werden in der init () Funktion gibt es die ‚Helfer‘ Klasse, _callback , die über die notwendigen Mittel für die App mit dem separaten Kommunikation zu initialisieren aufgerufen wird Isolat durch den Alarm Service im Hintergrund verwendet.
Zuletzt können Sie unten sehen, dass alle Parameterwerte, die nicht null sind, den spezifischen und auch statischen Eigenschaften zugewiesen sind, aus denen die Dienstprogrammklasse AlarmManager besteht . Viel Statisches ist hier nicht da.
Sie werden feststellen, dass viele der Eigenschaften und Funktionen, aus denen diese Klasse besteht, statisch sind. Die Wahl, statische Elemente in einer Klasse zu verwenden, sollte jedoch gut gelaunt sein. Da die Funktion init () beispielsweise statisch ist, kann sie überall, jederzeit und beliebig oft aufgerufen werden. Diese Tatsache erfordert einige zusätzliche Überlegungen. In diesem Fall ist die allererste einzeilige Anweisung im obigen Screenshot eine if-Anweisung: 'i f (_init) return _init;'. Dies war beim Schreiben dieser init () - Funktion erforderlich . Damit können Sie diese Funktion jetzt beliebig oft aufrufen. Unabhängig davon werden die erforderlichen Dienste und Plugins erst beim ersten Aufruf initialisiert. Wenn beispielsweise in einem Entwicklerteam der Aufruf der Funktion init () fälschlicherweise mehrmals ausgeführt wird, wird kein Schaden angerichtet. Ein weiteres wünschenswertes Merkmal einer Gebrauchsklasse. Sehen Sie, was ich hier mache? Das macht es irgendwie "kinderleicht". Richtig?
Initialisieren Sie Ihre Einstellungen
Wenn diese Parameter an diese statischen Variablen übergeben werden, bedeutet dies übrigens, dass Sie in unserem Beispiel mehr Optionen haben. Wenn die Funktion init () aufgerufen wird, könnten stattdessen die Einstellungen dann und dort angegeben worden sein. Dies würde es allen nachfolgenden Aufrufen der Funktionen oneShot (), oneShotAt () und periodic () ermöglichen, diese Einstellungen zu verwenden, wenn sie nicht explizit ihre eigenen bereitstellen. Ich habe dies unten demonstriert. Sie können die Unterschiede im Beispielcode sehen, wenn stattdessen die zusätzlichen Parameter in der Funktion init () verwendet wurden. Damit bleibt nur der Funktionsaufruf 'oneShot' mit seiner Dauer, seiner ID und der erforderlichen Rückruffunktion. Macht den Code etwas sauberer. Optionen!
D Platzieren Sie init () nicht in einer build () -Funktion ! Es scheint, dass die eigene init () - Funktion des Flutter-Plugins AndroidAlarmManager heißt. initialize (); neigt dazu, Nebenwirkungen oder Probleme zu verursachen. In einigen Fällen wird eine Neuerstellung initiiert (ähnlich wie beim Aufrufen der Funktion setState ()). Deshalb hat meine Utility-Klasse eine separate init () -Funktion. Es ist vorzuziehen, dass es am Anfang Ihrer App aufgerufen wird - beispielsweise in einem FutureBuilder-Widget mit MaterialApp. Überzeugen Sie sich selbst und versuchen Sie in Ihrem geänderten Beispiel, die Funktion AlarmManger.init () von initSettings () aus zu kommentieren, und platzieren Sie sie stattdessen direkt vor der Funktion oneShot () (siehe unten). In Ihrem Beispiel treten dann Fehler auf.
Machen Sie Ihren OneShot
ok, zurück zur Utility-Klasse. In der oneShot () -Funktion werden die ersten drei 'erforderlichen' Parameterwerte auf Gültigkeit geprüft und an die oneShot () -Funktion des Plugins weitergegeben . Alle außer dem Parameter 'Function', Rückruf . Stattdessen wird dies einem statischen Map-Objekt hinzugefügt, das durch die angegebene Ganzzahl-ID mit dem folgenden Befehl eindeutig identifiziert wird: _Callback.oneShots [id] = Rückruf . Wir werden früh genug darauf zurückkommen. Zuletzt stellen Sie fest, dass die statische Funktion oneShot () aufgerufen wird , die auch in der Hilfsklasse _Callback enthalten ist . Es ist die notwendige 'statische Funktion', die vom Plugin verwendet werden soll. Dadurch bleibt der Rest der Parameterwerte übrig, um diese vielen statischen Variablen mit dem Null-Koaleszenz-Operator zu erfassen. . Der Operator wird verwendet. Wenn also kein expliziter Parameter übergeben wird, werden stattdessen die Werte in diesen statischen Variablen verwendet. Kapiert? Diese statischen Variablen werden übrigens alle mit Standardwerten initialisiert, sodass keine Nullwerte an das Plugin selbst übergeben werden. Nett.
Gehen Sie kein Risiko ein
Beachten Sie, dass der Aufruf des Plugins selbst auch in einer try-catch- Anweisung enthalten ist. Das liegt daran, dass es sich um ein Programm von Drittanbietern handelt. Wir wissen nicht, was passieren könnte, und da dies eine Dienstprogrammklasse ist, möchten wir Ihre App nicht zum Absturz bringen, sondern eventuell auftretende Ausnahmen abfangen.
Wie jede gute Utility-Klasse verfügt auch diese Klasse über die Mittel, mit denen der Entwickler testen kann, ob der Vorgang erfolgreich war oder nicht. Wenn nicht, wird eine eventuell aufgetretene Ausnahme aufgezeichnet, damit der Entwickler damit umgehen kann. Dies wird unten im modifizierten Beispiel mit der neu eingefügten if- Anweisung demonstriert .
Mehr statisch
Weiter unten in der Utility-Klasse AlarmManager . Wir sehen die Funktion oneShotAt (). Da alle diese Funktionen statische Funktionen sind, müssen einige Sicherheitsvorkehrungen in den Code aufgenommen werden. Unter unglücklichen Umständen wird das Plugin beispielsweise möglicherweise nicht zuerst initialisiert, wenn diese onShotAt () -Funktion aufgerufen wird. Mit anderen Worten, die Funktion init () wurde nicht zuerst aufgerufen. Es könnte passieren, wenn es von der Öffentlichkeit benutzt wird. Wie Sie im folgenden Screenshot sehen können, wird eine solche Situation mit der Funktion assert () getestet . Dies ist in der Hoffnung, dass ein Entwickler einen solchen Fehler entdeckt, während er sich in der Entwicklung befindet. In der Produktion wird es von dieser if- Anweisung abgefangen, die auf die Funktion assert () folgt .
Beachten Sie, dass diese oneShotAt () -Funktion über ein eigenes Map-Objekt verfügt, um die übergebene 'callback'-Funktion zu speichern, und über eine eigene statische Funktion, _Callback.onShatAt (), die an die oneShotAt () -Funktion des Plugins übergeben wird . Dies alles impliziert übrigens, dass Sie diese Funktionen beliebig oft in Ihrer App aufrufen können, um eine beliebige Anzahl von Vorgängen zu planen, die in Zukunft ausgeführt werden sollen. Natürlich muss jedem ein eigener eindeutiger ID-Wert zugewiesen werden. Andernfalls wird jeder bereits geplante Vorgang mit einem neuen überschrieben, wenn er denselben ID-Wert verwendet. Das ist der Punkt bei der Verwendung eindeutiger IDs. Richtig?
Dies alles impliziert jedoch auch, dass Sie dieselbe ID verwenden können, jedoch zwischen den drei verschiedenen Funktionen oneShot (), oneShotAt () und periodic () getrennt. Denken Sie daran, dass sie ihre eigenen separaten Map-Objekte und statischen Funktionen haben. Diese Tatsache hat mir in meinem letzten Projekt gute Dienste geleistet, bei dem die verwendeten IDs genau die Werte waren, die in den primären Feldern der residenten Datenbank gefunden wurden. Optionen, Baby! Liebe es!
Ein Plugin-Blick
Ein kurzer Blick auf die Funktionen oneShot () und oneShotAt () des Flutter-Plugins zeigt , dass die Funktion oneShot () tatsächlich nur den Parameter an das Gegenstück oneShotAt () weitergibt . Beachten Sie, dass das 'CallbackHandle'-Objekt, das Sie im folgenden Screenshot sehen, von der Funktion _getCallbackHandle () stammt, die wiederum Flatters Framework-Funktion PluginUtilities.getCallbackHandle (Rückruf) nennt . Diese Operation "reißt" eine Kopie der Rückruffunktion ab, um Zugriff darauf zu haben und eine solche Funktion im Isolat aufzurufen, das im Hintergrund ausgeführt wird. Ich werde auch darauf zurückkommen.
Der Rückrufvorgang
Lassen Sie uns zunächst fortfahren und einen Blick auf die ' Hilfsklasse ' _Callback in der Bibliotheksdatei werfen . Unten sehen Sie, dass die Map-Objekte, die in den Callback-Funktionsobjekten hinzugefügt werden, in dieser Klasse als statische Eigenschaften definiert sind. Diese Klasse hat auch eine init () - Funktion und wird in der eigenen init () - Funktion des AlarmManger aufgerufen . In dieser init () -Funktion wird ein 'Kommunikationsport' mit drei spezifischen Namenskennungen registriert. Der Port wird vom Hintergrundisolate verwendet, um mit dem Vordergrundisolate zu kommunizieren, indem Nachrichten an ihn übergeben werden. Ratet mal, was die Werte dieser Namenskennungen sind? Sie erscheinen in der Abbildung unten in den Variablen gespeichert, _oneShot , _oneShotAt , und _periodic .
Wie der Name schon sagt, sind Isolate separate Speichersegmente
, die von Natur aus isoliert sind. Es gibt keine gemeinsame Nutzung von Erinnerungen. Es werden nur Nachrichten zwischen Isolaten weitergeleitet. Der Inhalt einer solchen Nachricht kann ein primitiver Wert (null, num, bool, double, String), eine Instanz eines SendPort- Objekts, eines List-Objekts oder eines Map-Objekts mit einem der zuerst genannten primitiven Werte sein.
Hören Sie im Hintergrund
Dem Port wird ferner ein "Listener" zugewiesen, der reagiert, wenn eine Nachricht empfangen wird, in diesem Fall vom Hintergrund Isolate, der den Alarmdienst ausführt. Der Listener hat die Form einer anonymen Funktion, die ein Map-Objekt als Parameter verwendet. Unten sehen Sie, dass das Map-Objekt einen ganzzahligen Wert (der zufällig die ID ist) und einen String enthält, in dem eine dieser 'Namenskennungen' gespeichert ist. Die case- Anweisung bestimmt dann, welcher 'Funktionstyp' ausgelöst werden soll. Sehen Sie, wie das funktioniert? Als Utility-Klasse ist natürlich alles in einer try-catch- Anweisung enthalten. Zum Beispiel haben wir keine Ahnung, was passieren wird, wenn die ausgewählte Funktion ausgeführt wird. Wir möchten eventuell auftretende Ausnahmen abfangen. Richtig?
Eine Nachricht schicken
Wie wird diese Nachricht an die App gesendet, die im Vordergrund ausgeführt wird? Nun, sobald diese Namenskennungen oben registriert sind, dann (siehe unten) eine der drei Dienstprogrammklassenfunktionen, AlarmManager . oneShot (), AlarmManager . oneShotAt () , und Alarmmanager . periodic () übergibt die drei entsprechenden statischen Funktionen _Callback . onShot (), _Callback . onShotAt () und _Callback . periodic (), direkt zum Flutter-Plugin. Auf diese Weise kann das Hintergrundisolat eine Nachricht an die App zurückgeben, die im Vordergrundisolat ausgeführt wird. Alle drei Arten von Anrufen sind unten aufgeführt.
Sie sehen, es sind diese drei entsprechenden statischen Funktionen, _Callback . onShot (), _Callback . onShotAt () und _Callback . periodic (), das sind 'die Brücke' vom Hintergrund Isolate zum Vordergrund Isolate. Wenn beispielsweise ein Alarm ausgelöst werden soll, ruft der Alarmdienst eine dieser drei statischen Funktionen auf. Beachten Sie, dass es sich nicht um die eigentliche Funktion handelt, die im Vordergrund-Isolat definiert ist, sondern um eine "abgerissene Kopie" davon. Aufgrund dieser Tatsache werden Sie ein kontraintuitives Verhalten feststellen. Beispielsweise ist jede statische Variable in dieser Funktion, die normalerweise im Vordergrundisolat definiert ist, im Hintergrundisolat null. Sie können dieses Phänomen selbst testen.
Wenn ich in unserem modifizierten Beispiel beispielsweise die Schaltfläche ein drittes Mal gedrückt habe, wissen wir, dass das Map-Objekt oneShots dieses eine Funktionsobjekt enthält , um den Bildschirm nach fünf Sekunden auszuführen und zu aktualisieren, und genau das tut es im Screenshot der 'Listener'-Routine unten. Dabei ist das Map-Objekt jedoch leer, wenn im Hintergrund darauf zugegriffen wird. Isolieren?! Wie ist das möglich? Dies ist möglich, da es sich um eine Kopie des Map-Objekts handelt und nicht um die im Vordergrund isolierte. Auch hier können Isolate nur "Nachrichten" aneinander weitergeben. Sie teilen keine Erinnerung.
Diese drei statischen Funktionen befinden sich wiederum in der Hilfsklasse _Callback , die nacheinander aufgelistet wird. Sie werden im folgenden Screenshot angezeigt. In jedem Fall können Sie sehen, dass das Vordergrundisolat mithilfe der 'Namenskennungen' referenziert wird und ein Kartenobjekt aus dem Hintergrundisolat übergeben wird. Beachten Sie, dass der Operator für den Zugriff auf bedingte Mitglieder ? wird verwendet, wenn die Suchoperation null zurückgibt. Dies ist beispielsweise der Fall, wenn der Name nicht vorhanden ist. Es ist unwahrscheinlich, dass dies jemals passiert, da dies alles internalisierter Code ist. Da wir jedoch eine Utility-Klasse sind, gehen wir kein Risiko ein. Richtig?
Alles dies ist am Ende der Bibliotheksdatei, und es ist hier , wo wir endlich den Wert dieses ‚name Bezeichner‘ in den Variablen zu sehen, _oneShot , _oneShotAt , und _periodic . Sie sind jeweils nach ihrem entsprechenden Funktionstyp benannt. Nicht sehr einfallsreich, aber es macht Sinn. Wir sehen auch, dass es sich um Variablen auf hoher Ebene handelt, die außerhalb einer Klasse oder einer Funktion auf hoher Ebene definiert sind. Tatsächlich handelt es sich um konstante Variablen mit dem Schlüsselwort const . Wie endgültige Variablen werden const-Variablen nur einmal initialisiert und können dann nicht mehr geändert werden. Im Gegensatz zu endgültigen Variablen werden sie beim Kompilieren der App definiert. Für unsere Bedürfnisse hier stehen sie daher auch Hintergrundisolaten zur Verfügung. Nett.
Wenn Sie all diese Isolate-Sachen nicht im Griff haben. Mach dir jetzt keine Sorgen. Dafür ist die Utility-Klasse gedacht. Im Gegensatz zum ursprünglichen Beispielcode für das Plugin müssen Sie sich keine Gedanken über die Einrichtung von Kommunikationsports oder die Verwendung einer statischen oder einer übergeordneten Funktion oder Variablen machen. Deshalb habe ich diese Klasse überhaupt geschrieben - also muss ich mir auch keine Sorgen machen. Aus diesem Grund werden solche Dienstprogrammklassen überhaupt geschrieben, sodass sie von unseren vielen Apps, die wir alle in Zukunft schreiben werden, immer wieder verwendet werden können. Richtig?
Prost.
→ Andere Geschichten von Greg Perry