Thông báo & Báo thức trong Flutter
Làm việc với Plugin Flutter, Android_Alarm_Manager.
Biết điều này! Plugin này chỉ hoạt động cho nền tảng Android ! Cá nhân tôi không biết bất kỳ iOS nào tương đương. Ngoài ra, một tháng sau khi xuất bản bài viết này, tôi đã tìm thấy một plugin cung cấp thông báo trên cả nền tảng Android và iOS. Tất nhiên, tôi đã viết một bài báo và điều đó nữa. Xem bên dưới.
Biết rằng nếu bạn muốn sử dụng plugin được mô tả ở đây, bạn phải tuân theo tệp readme của nó một cách rõ ràng để thiết lập mọi thứ một cách chính xác. Bạn đang sử dụng AndroidManfest.xml ít nhất phải trông giống như sau:
<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
Trong trường hợp này, nó dùng để tắt báo thức trong ứng dụng của bạn! Trong trường hợp của tôi, tôi thấy plugin Flutter, android_alarm_manager , đáp ứng nhu cầu của một ứng dụng gần đây mà tôi đang làm việc và vì vậy… tôi đã tạo một thói quen để dễ dàng làm việc với nó. Nếu bạn muốn, hãy lấy một bản sao , làm cho nó của riêng bạn và chia sẻ bất kỳ cải tiến nào bạn thực hiện. Mát mẻ?
Bây giờ nếu bạn có thời gian, vui lòng tiếp tục đọc những gì tôi thấy tôi phải làm để làm cho plugin này hoạt động gần như 'hoàn hảo' để dễ dàng và nhanh chóng đặt báo thức hoặc bất kỳ hoạt động nào khác được thực hiện 'trong nền' tại một số thời điểm trong tương lai khi ứng dụng đang chạy. Nó làm cho cuộc sống dễ dàng hơn một chút, và đó là một điều tốt. Đúng?
Chỉ ảnh chụp màn hình. Nhấp vào Đối với Gists.
Như mọi khi, tôi thích sử dụng ảnh chụp màn hình thay vì chủ để hiển thị mã trong bài viết của mình. Tôi thấy chúng dễ làm việc hơn và dễ đọc hơn. Tuy nhiên, bạn có thể nhấp / nhấn vào chúng để xem mã trong ý chính hoặc trong Github. Trớ trêu thay, đọc bài báo này về phát triển di động trên máy tính lại tốt hơn trên điện thoại. Bên cạnh đó, chúng tôi chủ yếu lập trình trên máy tính của mình; không phải trên điện thoại của chúng tôi. Còn bây giờ.
Hãy bắt đầu nào.
Cách tiếp cận của tôi ở đây là trước tiên trình bày lớp tiện ích này trong một ví dụ và trình bày cách sử dụng nó - do đó tận dụng lợi thế của plugin Flutter, android_alarm_manager . Trên thực tế, tôi sẽ sử dụng cùng một ví dụ được liệt kê trong trang ví dụ riêng của plugin . Tuy nhiên, ví dụ này đã được sửa đổi để sử dụng tệp thư viện được trình bày ở đây. Một bản sao của ví dụ này có sẵn cho bạn dưới dạng ý chính, android_alarm_manager . Sau ví dụ này, tôi sẽ đi qua các phần của chính lớp tiện ích mô tả đôi khi những gì cần phải làm để cho phép một lớp như vậy được sử dụng bởi những người kiên định là công chúng.
Giữ nó tĩnh
Trong ví dụ rất đơn giản này, bạn phải nhấn vào nút được hiển thị và 5 giây sau, hai số không như hình trong ảnh chụp màn hình bên dưới sẽ biến thành một. Chà! Tất nhiên, điều thực sự thú vị là những gì ẩn trong mã.
Lưu ý, tôi đã thay đổi mã so với mã gốc để phù hợp với các hoạt động không đồng bộ phải được thực hiện trước khi ứng dụng thực sự có thể bắt đầu chạy. Tôi đã sử dụng tiện ích FutureBuilder để thực hiện điều này. Khi làm như vậy, tôi đã xác định một hàm mới có tên initSettings () , để khởi tạo quy trình 'Tùy chọn được chia sẻ' được sử dụng để 'ghi nhớ' tổng số lần báo động được kích hoạt như trong ảnh chụp màn hình ở trên.
Bạn cũng có thể thấy trong hàm initSettings () được hiển thị bên dưới, nó đặt 'tổng số' thành 0 nếu đây là lần đầu tiên ứng dụng chạy. Tuy nhiên, ở phần đầu, quy trình thư viện, AlarmManager , được khởi tạo để thiết lập 'Dịch vụ báo thức' cụ thể cần thiết để thực hiện thông báo trên điện thoại Android.
Hãy đi sâu xuống mã ví dụ và xem điều gì tạo nên nút nhỏ đó. Lưu ý, quy trình thư viện sử dụng các tên giống nhau cho các tham số và chức năng tạo nên plugin Flutter được gạch dưới, Android_Alarm_Manager . Tốt hơn là nên nhất quán với những điều như vậy. Hơn nữa, giống như hàm oneShot () của plugin , phiên bản của thư viện này, sau khi được gọi, sẽ 'đợi' trong khoảng thời gian được chỉ định trước khi kích hoạt quy trình gọi lại được chỉ định. Trong trường hợp của ví dụ đã sửa đổi này, quy trình gọi lại là một hàm ẩn danh sẽ chạy sau khoảng thời gian 5 giây. Trên thực tế, trong ảnh chụp màn hình bên dưới, ứng dụng đã khởi động trở lại khi nút được nhấn lại cho biết, nhờ Tùy chọn chia sẻ, nút đã được nhấn hai lần kể từ lần đầu tiên nó được chạy. Chà.
Xem xét kỹ hơn hàm ẩn danh đó bên dưới, và chúng ta thấy nó được truyền một tham số duy nhất là kiểu, số nguyên. Bạn có thể đoán đó là cùng một giá trị id được truyền cho tham số thứ hai dưới dạng một số ngẫu nhiên bằng cách sử dụng các hàm Dart, Random (). NextInt (pow (2,31)) . Bây giờ tại sao phải truyền giá trị đó khi nó đã được truyền vào tham số ngay bên cạnh nó? Chúng tôi sẽ đạt được điều đó.
Bây giờ, bạn có thể thấy thêm bên dưới rằng hàm gọi lại, lần lượt, gọi hàm, _incrementCounter (). Ở đó, 'tổng số lần nhấn nút hiện tại được truy xuất từ quy trình' Tùy chọn được chia sẻ '. Sau đó, nó được cập nhật bởi một tài khoản cho lần nhấn nút hiện tại này và được lưu lại vào Tùy chọn chia sẻ. Màn hình của ứng dụng sau đó được cập nhật với biến tăng dần, _counter , bằng cách sử dụng hàm setState (). Bạn đã theo dõi tất cả những điều đó cho đến nay?
Giữ nó tĩnh
Không giống như ví dụ ban đầu (xem bên dưới), ví dụ này được phép sử dụng một hàm ẩn danh và không bắt buộc phải sử dụng cụ thể một hàm tĩnh. Tất nhiên, bạn cũng được phép sử dụng một hàm tĩnh trong ví dụ này - miễn là nó vẫn chấp nhận giá trị số nguyên duy nhất đó. Tuy nhiên, trong ví dụ ban đầu, nó phải là một hàm tĩnh hoặc một hàm cấp cao được xác định bên ngoài bất kỳ lớp nào trong tệp Dart của thư viện đó - một trong hai, bạn thấy, là một yêu cầu khi làm việc trực tiếp với plugin Flutter, Android_Alarm_Manager .
Tuy nhiên, nếu bạn đã theo dõi các bài viết của tôi, bạn biết tôi thích các tùy chọn. Đó là tất cả về việc có các lựa chọn với tôi. Tôi đã viết lớp tiện ích này để có nhiều sức chứa hơn - để cho phép các chức năng ẩn danh chẳng hạn. Do đó, với sự sắp xếp như vậy, việc chuyển giá trị số nguyên id đó như một tham số thực sự cho phép hàm trở thành một hàm Tĩnh, một hàm cấp cao hoặc một hàm ẩn danh. Tùy chọn! Một lần nữa, ảnh chụp màn hình của ví dụ ban đầu như sau:
Hãy chuyển sang lớp tiện ích, AlarmManager , chính nó. Một lần nữa, nó được thiết kế để hoạt động với plugin. Và một lần nữa, nhiều tham số là cùng một tham số được plugin sử dụng và do đó được chuyển đến plugin đó — nhưng không phải trước một số thử nghiệm tham số mở rộng để tìm các giá trị hợp lệ. Một đặc điểm cần thiết khác của các lớp tiện ích như vậy. Nó thực hiện tất cả công việc vì vậy bạn không cần phải làm. Đúng?
Trong ảnh chụp màn hình bên dưới, là phần đầu tiên của lớp tiện ích này. Trong hàm tĩnh của nó, init (), chúng ta thấy plugin thực sự đã được khởi tạo. Lưu ý, bất kỳ lỗi đáng tiếc nào có thể xảy ra trong quá trình khởi tạo sẽ được đưa vào câu lệnh try-catch . Các lớp tiện ích cũng cần phải làm điều đó. Tiếp theo trong init () chức năng, có những 'helper' lớp, _Callback , được gọi để khởi tạo các phương tiện cần thiết cho việc ứng dụng để giao tiếp với riêng Cô lập được sử dụng bởi các dịch vụ báo thức ở chế độ nền.
Cuối cùng, bạn có thể thấy bên dưới rằng bất kỳ và tất cả các giá trị tham số không null đều được gán cho các thuộc tính cụ thể và cũng như các thuộc tính Static tạo nên lớp tiện ích, AlarmManager . Rất nhiều Tĩnh diễn ra xung quanh đây không có ở đó.
Bạn sẽ tìm thấy nhiều thuộc tính và chức năng tạo nên lớp này là Tĩnh. Tuy nhiên, sự lựa chọn để sử dụng các thành viên tĩnh trong một lớp học nên được cân nhắc kỹ lưỡng. Ví dụ, vì hàm init () là Static, có nghĩa là nó có thể được gọi ở bất kỳ đâu, bất kỳ lúc nào và bất kỳ số lần nào. Thực tế đó đòi hỏi một số xem xét bổ sung. Trong trường hợp này, câu lệnh một dòng đầu tiên trong ảnh chụp màn hình ở trên là câu lệnh if: 'i f (_init) return _init;'. Nó là cần thiết khi viết hàm init () này. Với điều đó, bây giờ bạn có thể gọi hàm đó bao nhiêu lần tùy thích. Bất kể, các dịch vụ và plugin cần thiết chỉ được khởi tạo với cuộc gọi đầu tiên. Và do đó, trong một nhóm các nhà phát triển, chẳng hạn, nếu lệnh gọi hàm init () bị thực hiện nhầm nhiều lần, thì sẽ không có hại gì. Một đặc điểm mong muốn khác của một lớp tiện ích. Xem tôi đang làm gì ở đây? Làm cho nó trở nên 'dễ hiểu'. Đúng?
Init Your Settings
Nhân tiện, với các tham số đó được chuyển cùng với các biến tĩnh đó, điều đó có nghĩa là bạn có nhiều tùy chọn hơn trong ví dụ của chúng tôi. Khi hàm init () được gọi, thay vào đó các cài đặt có thể đã được chỉ định. Làm như vậy sẽ cho phép bất kỳ và tất cả các cuộc gọi tiếp theo đến các chức năng, oneshot (), oneShotAt (), và định kỳ (), để sử dụng những thiết lập nếu không cung cấp một cách rõ ràng của mình. Tôi đã chứng minh điều này bên dưới. Bạn có thể thấy sự khác biệt được thực hiện trong mã ví dụ nếu các tham số bổ sung trong hàm init () được sử dụng thay thế. Điều đó chỉ để lại lệnh gọi hàm 'oneShot' với thời lượng, id của nó và hàm gọi lại cần thiết. Làm cho mã sạch hơn một chút. Tùy chọn!
D Đừng đặt init () trong một hàm build () ! Nó sẽ xuất hiện hàm init () của plugin Flutter có tên là AndroidAlarmManager. khởi tạo ();, dễ gây ra các tác dụng phụ hoặc sự cố. Trong một số trường hợp, nó sẽ bắt đầu xây dựng lại (giống như gọi hàm setState ()). Đó là lý do tại sao lớp tiện ích của tôi có một hàm init () riêng biệt . Tốt hơn là nó được gọi gần đầu ứng dụng của bạn - trong một tiện ích FutureBuilder với MaterialApp chẳng hạn. Hãy tự mình xem và trong ví dụ đã sửa đổi của bạn, hãy thử bình luận về hàm AlarmManger.init () từ initSettings () và thay vào đó đặt nó ngay trước hàm oneShot () của nó (xem bên dưới.) Khi đó, ví dụ của bạn sẽ bắt đầu gặp lỗi.
Take Your oneShot
ok, quay lại lớp tiện ích. Trong hàm oneShot (), ba giá trị tham số 'bắt buộc' đầu tiên đang kiểm tra tính hợp lệ và được chuyển cùng với hàm oneShot () của riêng Plugin . Tất cả ngoại trừ tham số 'Hàm', gọi lại . Thay vào đó, nó được thêm vào đối tượng Bản đồ tĩnh được xác định duy nhất bởi id số nguyên được cung cấp bằng cách sử dụng lệnh sau, _Callback.oneShots [id] = callback . Chúng tôi sẽ quay lại điều đó đủ sớm. Cuối cùng, bạn nhận thấy có một lệnh gọi đến hàm tĩnh, oneShot (), cũng được tìm thấy trong lớp trợ giúp đó, _Callback . Nó viết tắt là 'chức năng tĩnh' cần thiết được plugin sử dụng. Điều này để lại phần còn lại của các giá trị tham số để nhận nhiều biến Tĩnh đó bằng cách sử dụng toán tử liên kết null, ?? . Toán tử được sử dụng để khi một tham số rõ ràng không được truyền, các giá trị trong các biến Tĩnh đó sẽ được sử dụng thay thế. Hiểu rồi? Nhân tiện, tất cả các biến tĩnh đó đều được khởi tạo với các giá trị mặc định nên cuối cùng không có giá trị null nào được chuyển đến chính plugin. Đẹp.
Không có cơ hội
Lưu ý, bản thân lệnh gọi đến plugin cũng được bao gồm trong câu lệnh try-catch . Đó là bởi vì đó là một chương trình của bên thứ ba. Chúng tôi không biết điều gì có thể xảy ra và vì đây là một lớp tiện ích, chúng tôi không muốn làm hỏng ứng dụng của bạn mà thay vào đó, hãy nắm bắt mọi trường hợp ngoại lệ có thể xảy ra.
Hơn nữa, giống như bất kỳ lớp tiện ích tốt nào, lớp này có phương tiện để nhà phát triển 'kiểm tra' xem hoạt động có thành công hay không. Nếu không, bất kỳ Ngoại lệ nào có thể đã xảy ra đều được ghi lại để nhà phát triển có thể xử lý nó. Điều này được minh họa bên dưới trong ví dụ đã sửa đổi với câu lệnh if mới được chèn .
Tĩnh hơn
Hơn nữa trong lớp tiện ích, AlarmManager . Chúng ta thấy hàm oneShotAt (). Một lần nữa, bởi vì tất cả các chức năng này là các chức năng Tĩnh, một số biện pháp bảo vệ cần được kết hợp trong mã. Ví dụ, trong những trường hợp không may, plugin có thể không được khởi tạo trước khi hàm onShotAt () này được gọi. Nói cách khác, hàm init () không được gọi trước. Nó có thể xảy ra khi được sử dụng bởi công chúng. Bạn có thể thấy trong ảnh chụp màn hình bên dưới, tình huống như vậy được kiểm tra bằng hàm khẳng định (). Điều này với hy vọng một nhà phát triển sẽ bắt được lỗi như vậy trong khi họ đang phát triển. Trong sản xuất, nó bắt bởi rằng nếu tuyên bố rằng theo assert () chức năng.
Lưu ý, đây oneShotAt function () có đối tượng Bản đồ riêng của mình để lưu trữ các thông qua trong chức năng 'gọi lại', và nó có chức năng riêng của nó tĩnh, _Callback.onShatAt (), được thông qua để riêng của plugin oneShotAt () chức năng. Tất cả điều này ngụ ý, bằng cách này, bạn có thể gọi các chức năng này bất kỳ số lần nào trong ứng dụng của bạn để lập lịch cho bất kỳ số lượng hoạt động nào xảy ra trong tương lai. Tất nhiên, mỗi cái phải được gán giá trị id duy nhất của riêng nó. Nếu không, bất kỳ hoạt động nào đã được lên lịch sẽ bị ghi đè bằng một hoạt động mới nếu nó xảy ra sử dụng cùng một giá trị id. Đó là điểm khi sử dụng id duy nhất. Đúng?
Tuy nhiên, tất cả điều này cũng có nghĩa bạn có thể sử dụng id giống nhau, nhưng giữa ba chức năng khác nhau, oneshot (), oneShotAt () và tuần hoàn () riêng biệt. Hãy nhớ rằng chúng có các đối tượng Bản đồ và các chức năng Tĩnh riêng biệt. Thực tế này phục vụ tốt cho tôi trong dự án gần đây của tôi, nơi id được sử dụng là các giá trị được tìm thấy trong các trường chính của cơ sở dữ liệu thường trú. Tùy chọn, em yêu! Yêu nó!
Một plugin Peek
Bây giờ hãy xem nhanh các hàm oneShot () và oneShotAt () của plugin Flutter và bạn có thể thấy rằng hàm oneShot () của nó, trên thực tế, chỉ chuyển tham số của nó cùng với đối tác oneShotAt () của nó. Lưu ý, đối tượng 'CallbackHandle' mà bạn thấy trong ảnh chụp màn hình bên dưới đến từ hàm _getCallbackHandle (), đến lượt nó, được gọi là hàm khung của Flutter, PluginUtilities.getCallbackHandle (gọi lại) . Thao tác này 'loại bỏ' một bản sao của hàm gọi lại để có quyền truy cập vào nó và gọi một hàm như vậy trong Isolate đang chạy ở chế độ nền. Tôi sẽ quay lại điều đó.
Hoạt động gọi lại
Bây giờ chúng ta hãy tiếp tục và xem qua 'lớp người trợ giúp,' _Callback , trong tệp thư viện . Bạn có thể thấy bên dưới các đối tượng Bản đồ đang thêm vào các đối tượng chức năng Gọi lại được định nghĩa trong lớp này dưới dạng thuộc tính Tĩnh. Lớp này cũng có một hàm init () và nó được gọi trong hàm init () của chính AlarmManger . Nó nằm trong hàm init () này, nơi một 'cổng giao tiếp' được đăng ký với ba định danh tên cụ thể. Cổng được Isolate nền sử dụng để giao tiếp với Isolate nền trước bằng cách chuyển các thông điệp tới nó. Đoán xem giá trị của các định danh tên đó là gì? Họ xuất hiện trong hình dưới đây được lưu trữ trong các biến, _oneShot , _oneShotAt , và _periodic .
Như tên của nó, phân lập, là các phân đoạn riêng biệt của bộ nhớ
được thiết kế, tốt, ... bị cô lập. Không có chia sẻ bộ nhớ. Chỉ có sự truyền thông điệp giữa các Isolates. Nội dung của một thông báo như vậy có thể là một giá trị nguyên thủy (null, num, bool, double, String), một thể hiện của đối tượng SendPort , đối tượng List hoặc đối tượng Bản đồ với bất kỳ giá trị nguyên thủy nào được đề cập trước tiên.
Nghe trong nền
Trong trường hợp này, cổng được gán thêm một 'người nghe' để phản ứng nếu và khi nhận được một thông báo, bằng cách Isolate nền chạy Dịch vụ báo động. Trình nghe ở dạng một hàm ẩn danh lấy đối tượng Bản đồ làm tham số của nó. Bạn có thể thấy bên dưới đối tượng Bản đồ chứa một giá trị số nguyên (ngẫu nhiên là id) và một Chuỗi lưu trữ một trong những 'định danh tên' đó. Sau đó, câu lệnh case xác định 'kiểu' hàm nào sẽ kích hoạt. Xem cách đó hoạt động như thế nào? Tất nhiên, là một lớp tiện ích, tất cả đều nằm trong một câu lệnh try-catch . Ví dụ, chúng tôi không biết điều gì sẽ xảy ra khi chạy hàm đã chọn. Chúng tôi muốn nắm bắt bất kỳ Ngoại lệ nào có thể xảy ra. Đúng?
Gửi tin nhắn
Vậy làm thế nào mà tin nhắn đó được gửi đến ứng dụng đang chạy ở phía trước? Chà, sau khi các định danh tên đó được đăng ký ở trên, thì (xem bên dưới) bất kỳ hàm nào trong ba hàm của lớp tiện ích, AlarmManager . oneShot (), AlarmManager . oneShotAt () , và AlarmManager . Tuần hoàn (), sẽ chuyển ba hàm Tĩnh tương ứng, _Callback . onShot (), _Callback . onShotAt () và _Callback . định kỳ (), trực tiếp đến plugin Flutter. Làm như vậy sẽ cho phép Isolate nền sau đó chuyển một thông báo trở lại ứng dụng đang chạy trong Isolate nền trước. Tất cả ba loại cuộc gọi được liệt kê dưới đây.
Bạn thấy đấy, đó là ba hàm Tĩnh tương ứng, _Callback . onShot (), _Callback . onShotAt () và _Callback . period (), là 'cầu nối' từ Isolate nền đến Isolate nền trước. Ví dụ: khi đến lúc đặt báo thức, Dịch vụ báo thức sẽ gọi một trong ba chức năng Tĩnh này. Lưu ý, khi nó xảy ra, nó không phải là chức năng thực sự được xác định trong Isolate tiền cảnh, mà là một 'bản sao bị xé nhỏ' của nó. Bạn sẽ thấy một số hành vi phản trực giác vì thực tế này. Ví dụ, bất kỳ biến Static nào trong hàm đó thường được xác định trong Isolate nền trước sẽ là rỗng trong Isolate nền. Bạn có thể tự kiểm tra hiện tượng này.
Ví dụ: trong ví dụ đã sửa đổi của chúng tôi, nếu tôi nhấn nút lần thứ ba, chúng tôi biết đối tượng Bản đồ, oneShots , có một đối tượng Chức năng trong đó để chạy và cập nhật màn hình sau năm giây và nó chỉ thực hiện điều đó trong ảnh chụp màn hình của quy trình 'Người nghe' bên dưới. Tuy nhiên, trong quá trình này, đối tượng Bản đồ đó trống nếu được truy cập trong nền Isolate ?! Làm thế nào là có thể? Điều đó có thể xảy ra vì đó là bản sao của đối tượng Bản đồ chứ không phải bản sao ở tiền cảnh Cô lập. Một lần nữa, các Isolates chỉ có thể chuyển 'thông điệp' cho nhau. Chúng không chia sẻ bộ nhớ.
Một lần nữa, ba hàm Tĩnh này nằm trong lớp trợ giúp, _Callback , được liệt kê lần lượt. Chúng được hiển thị trong ảnh chụp màn hình bên dưới. Trong mỗi cái, bạn có thể thấy phần Isolate nền trước được tham chiếu bằng cách sử dụng 'định danh tên' và được chuyển một đối tượng Bản đồ từ phần Isolate nền. Lưu ý, toán tử truy cập thành viên có điều kiện, ?. , được sử dụng trong trường hợp thao tác tra cứu trả về null. Ví dụ: nó sẽ làm như vậy nếu tên không tồn tại. Nó không bao giờ có khả năng xảy ra vì đây là tất cả mã nội bộ, nhưng là một lớp tiện ích, chúng tôi không có bất kỳ cơ hội nào. Đúng?
Tất cả điều này là ở phần cuối của tập tin thư viện, và nó ở đây, nơi cuối cùng chúng ta thấy giá trị của những 'tên định danh' trong các biến, _oneShot , _oneShotAt , và _periodic . Chúng được đặt tên theo loại chức năng tương ứng của chúng. Không quá tưởng tượng, nhưng nó có ý nghĩa. Chúng tôi cũng thấy chúng là các biến cấp cao được xác định bên ngoài một lớp hoặc hàm cấp cao. Trên thực tế, chúng là các biến không đổi với từ khóa, const . Giống như các biến cuối cùng, các biến const chỉ được khởi tạo một lần và sau đó không thể thay đổi được. Không giống như các biến cuối cùng, chúng được xác định khi ứng dụng được biên dịch. Do đó, đối với nhu cầu của chúng tôi ở đây, chúng có sẵn cho cả các Isolates nền. Đẹp.
Nếu bạn không có khả năng xử lý tất cả những thứ Isolate này. Đừng lo lắng về nó ngay bây giờ. Đó là những gì lớp tiện ích dành cho. Không giống như mã ví dụ plugin ban đầu, bạn không phải lo lắng về việc thiết lập 'cổng giao tiếp' hoặc khi nào sử dụng một hàm hoặc biến Static hoặc cấp cao. Đó là lý do tại sao tôi đã viết lớp này ngay từ đầu - vì vậy tôi cũng không phải lo lắng về tất cả những thứ đó. Đó là lý do tại sao các lớp tiện ích như vậy được viết hoàn toàn - vì vậy chúng có thể được sử dụng lặp đi lặp lại bởi nhiều ứng dụng mà tất cả chúng ta sẽ viết trong tương lai. Đúng?
Chúc mừng.
→ Những câu chuyện khác của Greg Perry