Cannot run with sound null safety because dependencies don't support null safety
Android Studio
Go to Run > Edit Configurations > Add Additional Run args and add --no-sound-null-safety.
Cascades Notation(...) allows chaining a sequence of operations on the same object. Besides, fields (data-members) can be accessed using the same.
class Person { String name; int age: Person(this.name, this.age); void data() => print("$name is $age years old."); } //Without Cascade Notation Person person = Person("Richard", 50); person.age = 22; person.name += " Parker"; person.data(): //Cascade Notation with Object of Person Person("Jian", 21) ..age = 22 ..name += " Yang" ..data(); //Cascade Notation with List <String>["Natasha", "Steve", "Peter", "Tony"] ..sort() ..forEach((name) => print("\n$name"));
The cascade operator (..) is another handy Dart feature that helps you streamline object initialization. Instead of referencing the object name repeatedly, you can chain multiple property assignments and method calls to the same object.
myClass ..property1 = value1 ..property2 = value
Do
@override Widget build(BuildContext context) { return Scaffold( body: Column( children: const [ Widget(), Widget(), Widget() ] ) ); }
Don't
@override Widget build(BuildContext context) { return Scaffold( body: Column( children: const [ Row( children: const [ Text(), Text() ] ), Padding( padding: EdgeInsets.all(16.0), child: Column( children: [ Row( children: const [ Text(), Text() ] ), Text() ] ) ) ] ) ); }
Conclusion: Leads to code that is more readable and easier to reason about.
AndroidManifest.xml
<uses-permission android:name="android.permission.VIBRATE"/>
import "package:flutter/services.dart"; MaterialButton( onPressed: () { HapticFeedback.heavyImpact(); HapticFeedback.mediumImpact(); HapticFeedback.lightImpact(); //Use any one of the above }, child: Text("Vibrate") );
If we have a function that invokes a method with the same arguments as are passed to it, you don’t need to manually wrap the call in a lambda.\
Do
List<String> names = [] names.forEach(print);
Don't
List<String> names = [] names.forEach((name) { print(name); });
Don't do this
class FutureDemoPage extends StatelessWidget { /// Function that will return a /// "string" after some time /// To demonstrate network call /// delay of [2 seconds] is used /// /// This function will behave as an /// asynchronous function Future<String> getData() { return Future.delayed(Duration(seconds: 2), () { return "I am data"; // throw Exception("Custom Error"); }); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( appBar: AppBar( title: Text('Future Demo Page'), ), body: FutureBuilder( builder: (ctx, snapshot) { // Checking if future is resolved or not if (snapshot.connectionState == ConnectionState.done) { // If we got an error if (snapshot.hasError) { return Center( child: Text( '${snapshot.error} occurred', style: TextStyle(fontSize: 18), ), ); // if we got our data } else if (snapshot.hasData) { // Extracting data from snapshot object final data = snapshot.data as String; return Center( child: Text( '$data', style: TextStyle(fontSize: 18), ), ); } } // Displaying LoadingSpinner to indicate waiting state return Center( child: CircularProgressIndicator(), ); }, // Future that needs to be resolved // inorder to display something on the Canvas future: getData(), ), ), ); } }
Do this
Future<String> _value; @override initState() { super.initState(); _value = getValue(); } FutureBuilder<String>( future: _value, // other arguments )
Double dots(..) i.e cascade operator
Double dots(..) is known as cascade notation (allow you to make a sequence of operations on the same object). It allows you to not repeat the same target if you want to call several methods on the same object.This often saves you the step of creating a temporary variable and allows you to write more fluid code. Normally, we use the below way to define several methods on the same object.
//before var paint = Paint(); paint.color = Colors.black; paint.strokeCap = StrokeCap.round; paint.strokeWidth = 5.0; //after var paint = Paint() ..color = Colors.black ..strokeCap = StrokeCap.round ..strokeWidth = 5.0;
Triple dots(…) i.e. Spread Operator
Triple dots(…) also known as spread operator which provide a concise way to insert multiple values into a collection.You can use this to insert all the elements of a list into another list:
//before var list = [1, 2, 3]; var list2 = []; list2.addAll(list); //after var list = [1, 2, 3]; var list2 = [0, ...list];
To download a file, first create a Cloud Storage reference to the file you want to download.
You can create a reference by appending child paths to the root of your Cloud Storage bucket, or you can create a reference from an existing gs:// or https:// URL referencing an object in Cloud Storage.
// Create a storage reference from our app final storageRef = FirebaseStorage.instance.ref(); // Create a reference with an initial file path and name final pathReference = storageRef.child("images/stars.jpg"); // Create a reference to a file from a Google Cloud Storage URI final gsReference = FirebaseStorage.instance.refFromURL("gs://YOUR_BUCKET/images/stars.jpg"); // Create a reference from an HTTPS URL // Note that in the URL, characters are URL escaped! final httpsReference = FirebaseStorage.instance.refFromURL( "https://firebasestorage.googleapis.com/b/YOUR_BUCKET/o/images%20stars.jpg");
Download the file to a UInt8List with the getData() method. This is the easiest way to download a file, but it must load the entire contents of your file into memory. If you request a file larger than your app's available memory, your app will crash. To protect against memory issues, getData() takes a maximum amount of bytes to download. Set the maximum size to something you know your app can handle, or use another download method.
final islandRef = storageRef.child("images/island.jpg"); try { const oneMegabyte = 1024 * 1024; final Uint8List? data = await islandRef.getData(oneMegabyte); // Data for "images/island.jpg" is returned, use this as needed. } on FirebaseException catch (e) { // Handle any errors. }
The writeToFile() method downloads a file directly to a local device. Use this if your users want to have access to the file while offline or to share the file in a different app. writeToFile() returns a DownloadTask which you can use to manage your download and monitor the status of the download.
final islandRef = storageRef.child("images/island.jpg"); final appDocDir = await getApplicationDocumentsDirectory(); final filePath = "${appDocDir.absolute}/images/island.jpg"; final file = File(filePath); final downloadTask = islandRef.writeToFile(file); downloadTask.snapshotEvents.listen((taskSnapshot) { switch (taskSnapshot.state) { case TaskState.running: // TODO: Handle this case. break; case TaskState.paused: // TODO: Handle this case. break; case TaskState.success: // TODO: Handle this case. break; case TaskState.canceled: // TODO: Handle this case. break; case TaskState.error: // TODO: Handle this case. break; } });
If you already have download infrastructure based around URLs, or just want a URL to share, you can get the download URL for a file by calling the getDownloadURL() method on a Cloud Storage reference.
final imageUrl = await storageRef.child("users/me/profile.png").getDownloadURL();
There are a number of reasons why errors may occur on download, including the file not existing, or the user not having permission to access the desired file. More information on errors can be found in the Handle Errors section of the docs.
final islandRef = storageRef.child("images/island.jpg"); final appDocDir = await getApplicationDocumentsDirectory(); final filePath = "${appDocDir.absolute}/images/island.jpg"; final file = File(filePath); final downloadTask = islandRef.writeToFile(file); downloadTask.snapshotEvents.listen((taskSnapshot) { switch (taskSnapshot.state) { case TaskState.running: // TODO: Handle this case. break; case TaskState.paused: // TODO: Handle this case. break; case TaskState.success: // TODO: Handle this case. break; case TaskState.canceled: // TODO: Handle this case. break; case TaskState.error: // TODO: Handle this case. break; } });