https://reprom.io/the-beauty-...
在閱讀 Flutter 時,我讀到最多的缺點之一就是使用 Dart 編程語言。它尚未 Kotlin 那麼成熟,這是我讀到的最常被說起的論點之一。在我看來(我認可這可能會引發爭議) ,Dart 是一種偉大的語言,我不會在 Flutter 建立應用程序時爲其餘任何語言改變它,我是在 Kotlin 專業地建立 android 應用程序以後說的,順便說一句,這也是一種優雅而美麗的語言。html
在這篇文章中,我打算展現我最喜歡的 Dart 編程語言的 4 個特性,沒有特定的順序; 讓咱們看看咱們如何利用這個現代工具:android
最近在 2.12 版本中添加(包括在 Flutter 2.0 中)。在任何僞裝堅實和高效的現代語言中,空安全都是必須的。這就是爲何 Dart 團隊一直致力於實現聲音 null 安全,這意味着咱們能夠有能夠爲空的類型和不能爲空的類型,若是咱們嘗試在後面執行一個不安全的操做,咱們會在應用程序構建以前獲得一個編譯錯誤:git
// This is a String that can be null String? nullVar; // This String cannot be null, the compiler forces me // to set it a value because of its non-nullable nature. String nonNullVar = 'I am not null'; // Alternatively, I can specify that the value will be // set later, but the property continues to be non-nullable. late String lateNonNullVar; // If I want to call a method on an instance of a type // that can be null, I need first to do a runtime check that // its value is not null. if (nullVar != null) { nonNullVar.toLowerCase(); } // Or call it using the '?' operator, which means that the // method will only be called if the instance is not null: nullVar?.toLowerCase(); // If the type is not nullable I can safely call any // method on it directly. nonNullVar.toLowerCase(); // Always remember to initialize late vars, or you // will get an exception when trying to access its members. lateNonNullVar = 'some value'; lateNonNullVar.toLowerCase();
就像在 Javascript 中咱們有 Promises,在 Dart 中咱們有 Futures,其中 async/await 是主要的關鍵詞,這給了咱們開發者一個簡單而強大的方法來處理異步操做:github
使用 Futures,咱們能夠輕鬆地中止當前操做流,等待某個異步操做完成,而後繼續工做。編程
// To specify that a function will perform an asynchronous // operation (like doing a network request or reading from // a database) we mark it with the 'async' keyword: asyncFunction() async { // ... } // Use the 'await' keyword to stop the flow until the function // has completed its task: await asyncFunction(); // You must declare a function as 'async' if it contains // calls to other async functions: main() async { await asyncFunction(); } // If the async function returns a value, wrap it within // a Future. For instance, the following function // would do a network call and return its result: Future<NetworkResult> doNetworkCall() async { // ... } final result = await doNetworkCall(); // But what if the network request fails and an exception // is thrown? Just wrap the call in a try/catch block: late NetworkResult result; try { result = await doNetworkCall(); } on NetworkException catch (e) { // Handle error }
須要指出的是,即便使用 async/await 關鍵字,全部的操做都是在同一個線程中執行的,若是咱們須要具體的性能要求,咱們可使用 isolates 產生替代線程。api
在 Dart 中,咱們在定義函數參數時有多個選項:安全
// You can define mandatory parameters as you do in // many other languages, specifying their type and setting a label: functionWithMandatoryParameters(String someString, int someNumber) { // ... } // You are forced to send the defined parameters // when using the function: functionWithMandatoryParameters('some_string', 46); // You can however specify that the parameters are optional: // (note that the type must be defined as nullable, precisely because // there's no guarantee that the caller will send a value) functionWithOptionalParams( {String? optionalString, int? optionalNumber}) { // ... } // You can call this function without sending any values, // or specifying a value for an optional parameter with its label: functionWithOptionalParams(); functionWithOptionalParams(optionalString: 'some_string'); functionWithOptionalParams( optionalString: 'some_string', optionalNumber: 46); // When defining optional parameters, you can set a default value // that will be used in case that there is no value sent by the caller: functionWithDefaultValue({String someString = 'default'}) { // ... } // The value of someString is 'default' functionWithDefaultValue(); // The value of someString is 'some_string' functionWithDefaultValue(someString: 'some_string'); // Lastly, you can even define mandatory named parameters with the // 'required' keyword, this is useful to enhance code readability. createUser( {required String username, required String name, required String surname, required String address, required String city, required String country}) { // ... } createUser( username: 'Ghost', name: 'John', surname: 'Doe', address: '3590 Mill Street', city: 'Beaver', country: 'US');
軟件開發中最不流行的趨勢之一是重組而不是繼承,這意味着使用相似組件的元素向類添加功能,而不是從父類繼承。這種方法容許咱們輕鬆地添加封裝的功能,而無需處理複雜的繼承層次結構。微信
例如,假設您有一個登陸邏輯,您可能但願在應用程序中的不一樣位置使用它。您可使用這個邏輯建立一個組件(mixin) ,而後在須要時重用它:異步
abstract class AuthUtils { Future<User> login() async { // Here we can add the login logic that will later be reused // in any class that ads this mixin. } } class LoginPage extends StatefulWidget { LoginPage({Key? key}) : super(key: key); @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> with AuthUtils { @override Widget build(BuildContext context) { return FutureBuilder<User>( future: login(), // Calling the mixin function builder: (BuildContext context, AsyncSnapshot<User> snapshot) { // ... }, ); } }
這裏的優勢是,咱們能夠爲所欲爲地添加任意多的 mixin,而不是僅經過使用繼承從一個父類繼承。async
這些只是 Dart 提供給開發者的多個有用特性中的 4 個。若是你想了解更多,我建議你去參觀 Dart 語言之旅,它以一種很是友好的方式解釋了這門語言的每個細節。
https://dart.dev/guides/langu...
© 貓哥
https://github.com/ducafecat/...
https://github.com/ducafecat/...
https://ducafecat.tech/catego...
https://ducafecat.tech/catego...
https://space.bilibili.com/40...
https://space.bilibili.com/40...
https://space.bilibili.com/40...
https://space.bilibili.com/40...
https://space.bilibili.com/40...
https://space.bilibili.com/40...