Old iron remember to forward, Brother Cat will present more Flutter good articles ~~~~
Wechat Flutter technology group Ducafecat
The original
Reprom. IO/the – beauty -…
reference
- The dart. Dev/codelabs/as…
- Medium.com/flutter-com…
- The dart. Dev/guides/lang…
- API. Dart. Dev/stable / 2.13…
The body of the
One of the drawbacks I read most about Flutter is the use of the Dart programming language. It’s not as mature as Kotlin, and this is one of the most frequently cited arguments I’ve read. Dart is a great language in my opinion (and I admit it can be controversial) and I wouldn’t change it for any other language when CREATING apps for Flutter. I say this after Kotlin professionally created Android apps, which is also an elegant and beautiful language, by the way.
In this article, I intend to present four of my favorite features of the Dart programming language, in no particular order; Let’s see how we can use this modern tool:
Null safety
Recently added in Flutter 2.12 (including Flutter 2.0). Air safety is a must in any modern language that pretends to be solid and efficient. That’s why the Dart team has been working on sound null safety, which means we can have nullable types and nullable types, and if we try to perform an unsafe operation later, we’ll get a compile error before the application builds:
// 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();
Copy the code
Async / await
Just as in Javascript we have Promises, in Dart we have Futures where async/await is the main keyword, this gives us developers a simple and powerful way to handle asynchronous operations:
With Futures, we can easily stop the current operation flow, wait for an asynchronous operation to complete, and then continue working.
// 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
}
Copy the code
It should be noted that even with the async/await keyword, all operations are performed in the same thread, and if we need specific performance requirements, we can use an alternative thread called Generate.
Various methods for defining function parameters
In Dart, we have several options when defining function parameters:
// 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');
Copy the code
Composition with mixins
One of the least popular trends in software development is refactoring rather than inheritance, which means adding functionality to a class using component-like elements rather than inheriting from a parent class. This approach allows us to easily add encapsulated functionality without having to deal with complex inheritance hierarchies.
For example, suppose you have a logon logic that you might want to use at different places in your application. You can use this logic to create a component (mixin) and then reuse it as needed:
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) {
// ...}); }}Copy the code
The advantage here is that we can add as many mixins as we want, rather than just inheriting from a parent class using inheritance.
conclusion
These are just four of the many useful features Dart offers developers. If you want to learn more, I suggest you visit the Dart Language Tour, which explains every detail of the language in a very friendly way.
The dart. Dev/guides/lang…
The elder brother of the © cat
ducafecat.tech/
github.com/ducafecat
The issue of
Open source
GetX Quick Start
Github.com/ducafecat/g…
News client
Github.com/ducafecat/f…
Strapi manual translation
getstrapi.cn
Wechat discussion group Ducafecat
A series of collections
The translation
Ducafecat. Tech/categories /…
The open source project
Ducafecat. Tech/categories /…
Dart programming language basics
Space.bilibili.com/404904528/c…
Start Flutter with zero basics
Space.bilibili.com/404904528/c…
Flutter combat news client from scratch
Space.bilibili.com/404904528/c…
Flutter component development
Space.bilibili.com/404904528/c…
Flutter Bloc
Space.bilibili.com/404904528/c…
Flutter Getx4
Space.bilibili.com/404904528/c…
Docker Yapi
Space.bilibili.com/404904528/c…