Dart Syntax sweep – Package Access – Generics – Exception – Async -mixin: Dart syntax sweep – Package Access – Generics – Exception – Async – Mixin

An article on asynchrony in Dart is on its way, and I’ll explain it to you with good graphics and vivid examples. Let’s take a look.


1. The synchronous

1.1: Demonstration of synchronization

Program synchronization is performed sequentially: one task is completed before moving on to the next,

Like the code below, it takes 15 minutes to sweep the floor before boiling water, and you have to wait for the water to boil before washing clothes.

Main () {print("A task: sweep the floor for 15min"); Print ("B task: boil water for 25min"); Print ("C task: laundry 25min"); }Copy the code

1.2: Disadvantages of synchronization

If you treat a person as a labor force, then doing so will reduce the utilization of labor.

For the cruel exploiter, such a way of working is obviously not satisfactory to him: it is completely possible to boil the water first, then sweep the floor after the fire, then dump the garbage, then wash the clothes, wait until the water boils, stop washing the clothes, rinse the water and then wash the clothes, this is the mentality of the exploiter


1.3: About asynchrony

The CPU is the labor force, and the programmers are the cruel exploiters. In order for it to work as hard as it can, asynchrony is created

When we need to connect to the Internet, read files, do database operations, it’s like waiting for the water to boil and you don’t want a labor force standing around waiting for the water to boil, so you want to tell it, “Go wash your clothes now, come back and flush when the water boils” and that raises the question, “How do I know who’s boiling?” It’s an event that’s happening at some indeterminate point in the future and you need to have something to mark it, like when the water boils it’s going to hum, or else it’s going to keep doing laundry and it’s not going to dry?


2, read from the file to see asynchrony

2.1: About Future objects

When reading the File, you’ll be surprised to see the readXXX method on the File object:

Method names that do not have the Sync suffix are Future objects. This means that the operation returns a Future object. You can see that the Future has a then method

---->[sky_engine/lib/async/future.dart:601]----
Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
Copy the code

The then method is used to register callbacks to be called on future completion.

When the future is completed with a value, the value is called back in [onValue]. If the Future is already complete, the callback will not be invoked immediately, but will be scheduled later in the microtask. You can also see an optional argument, onError, which will be called back when an error is executed


2.2: Read files asynchronously using the Future

Now that you know that a callback can be passed in then to get the contents of the file, it’s easy

If the file is read asynchronously, the file is read asynchronously. If the file is read asynchronously, the file is read asynchronously and the file is read asynchronously

import 'dart:io'; The main () {var path = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / diffuse. TXT'; Future<String> futureStr = File(path).readAsString(); futureStr.then((value){ print(value); }); Print ("======= look at the console, where am I? = = = = = = "); }Copy the code


2.3:asyncandawaitAsynchronous file reading

Adding the async annotation to a method name indicates that the method is an asynchronous method in which asynchronous operations can be performed

For example, to read files asynchronously, we just need to prefix the Future object with await to get the Future value.

import 'dart:io'; main() { readByAsync(); Print ("======= look at the console, where am I? = = = = = = "); } readByAsync () is async {var path = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / diffuse. TXT'; var result = await File(path).readAsString(); print(result); }Copy the code


2.4: Synchronously reads files

Synchronous reading is like waiting for the water to boil and then doing something else, reading the file and receiving it before executing the next line of code

main() { readBySync(); Print ("======= look at the console, where am I? = = = = = = "); } readBySync () {var path = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / diffuse. TXT'; var result = File(path).readAsStringSync(); print(result); }Copy the code


3.Dart Stream

A Stream is nothing new. Almost every language has a Stream operation.

The Stream Stream in Dart is explained in detail here. Let’s start with a few ways to create a Stream

Factory stream.empty () = _EmptyStream<T>// Creates an empty Stream stream.fromFuture (Future<T> Future)// created by a Future object Stream.fromfutures (Iterable<Future<T>> futures)// Stream. FromIterable (Iterable<T> elements)// Stream Stream.periodic(Duration period,[T computation(int computationCount)])// Periodic streamsCopy the code

3.1: The most important point!

I think the most important thing to know about a Stream is how does it differ from a list

  • Ordinary list traversal
var fishes = ["A", "B", "C"]; fishes.forEach((e){ print(e); }); print("===="); ---->[Printed result]---- A B C ====Copy the code
  • Flow traversal
void byStream() { var fishes = ["A", "B", "C"]; var stream =Stream.fromIterable(fishes); stream.forEach((e){ print(e); }); print("===="); } ---->[Printed result]---- ==== A B CCopy the code

3.2: Explanations about both

The main difference between a Stream and a list is that it traverses asynchronously

The moment a List is iterated, I know what’s in it, how many elements are in it, how I can manipulate it that way. List is like a hahaqueen three thousand in the palace waiting for you to operate at any time, Stream is hahaqueen three thousand is coming on the way, you can’t do anything. A Stream is like a Stream. You just know that the fish in it are swimming towards you. You can’t fish them out at this moment, and you don’t know when they will reach you.

  • What's the point

Now, the evil me secretly poisons A while the fish is swimming, and then in the future you get A and eat it and die silly

This is how elements in a Stream can be controlled and manipulated until they reach their destination. You don’t know how many fish I hack.


3.3: subscribe to:listen

That’s you up front, waiting for the fish to come. Indicate that you subscribe to elements in the stream.

If the wind is calm and no one poisons you, you will surely get the three fish swimming towards you in the river.

var fishes = ["A", "B", "C"]; var stream =Stream.fromIterable(fishes); Stream. listen((fish)=>print(" get $fish")); ---->[print result]---- get A get B get CCopy the code
  • Subscribe to the callback
var fishes = ["A", "B", "C"]; var stream = Stream.fromIterable(fishes); Stream. listen((fish) => print(" $fish"), onDone: () => print(" $fish"), () => print(" error "), cancelOnError: false); // Whether to unsubscribe in case of errorCopy the code

3.4: Cancellation of subscription

OnDone does not call back once the subscription is cancelled, even if you have the last fish

Here’s what it means: After you get a B, you cancel your subscription and walk away

var fishes = ["A", "B", "C"]; var stream = Stream.fromIterable(fishes); var you = stream.listen(null); OnData ((fish){print(" get $fish"); If (fish=="B"){// If (fish=="B"){// Cancel (); }}); You. OnError ((e)=>print(" $e")); You. OnDone (()=>print(' all '));Copy the code

3.5: Element addition in Stream

There are only three fish in it, and you feel very uncomfortable. Then the kind caretaker says, “I’ll add it to you now.

StreamController has a stream object that you can stream through and because it’s asynchronous, it can be added after you subscribe, and it doesn’t affect your access to the data, just like when you subscribe, the administrator puts the fish in the water and the fish comes to you.

StreamController controller = StreamController(); controller.add("A"); controller.add("B"); controller.add("C"); Controller.stream. listen((fish) => print(" get $fish")); controller.add("D"); controller.add("E"); controller.add("F"); controller.close();Copy the code

3.6: Evil ME online

Evil I come, in the middle of the interception of a fish. Remember this picture, the idea of a Stream is pretty much the same.

StreamController controller = StreamController(); controller.add("A"); controller.add("B"); controller.add("C"); Controller.stream.map ((fish) {if (fish == "C") {print(" I have poisoned C"); Return "poisoned C"; } if(fish=="D"){print("D "); Return "D bone "; } return fish; }). Skip (2) / / to throw out the first two. Take (2) / / in the end can only take two. Listen ((fish) = > print (" silly you got $fish ")); controller.add("D"); controller.add("E"); controller.add("F"); controller.close(); ---->[print result]---- I have poisoned C silly you have got the poisoned C D has been eaten by me silly you have got the bones of DCopy the code

3.7. Your friends are here, too

When fish B is added to the fishpond, your friend stands next to you and subscribes too, at this point he can only listen to the later additions.

Using the broadcast method allows a Stream to be listened to by multiple people otherwise :Stream has already been listened to.

StreamController<String> controller = StreamController<String>.broadcast(); StreamSubscription you = Controller.stream.listen ((value) => print(' $value ')); controller.sink.add("A"); controller.sink.add("B"); StreamSubscription youFriend = Controller.stream.listen ((value) => print(' $value ')); controller.sink.add("C"); controller.sink.add("D"); controller.close();Copy the code

4.Dart file system

At the top of the file in Dart is the FileSystemEntity abstract class, which has three children:

File interface, Directory interface, Link interface, three of which have a private class to inherit respectively

Folder class Directory
---->[constructor]---- Directory(String path)// from Directory. FromUri (Uri Uri)// fromUri Directory. FromRawPath (Uint8List // From the native path Uri get Uri; Directory get current; Directory get absolute; ----> ---- Future<Directory> create({bool recursive: false}); Future<Directory> createTemp([String prefix]); Future<Directory> rename(String newPath); // Rename Stream<FileSystemEntity> list(// recursive {bool recursive: false, bool followLinks: true}); ----> ---- void createSync({bool recursive: false}); Directory createTempSync([String prefix]); Directory renameSync(String newPath); Stream<FileSystemEntity> list( {bool recursive: false, bool followLinks: true});Copy the code
var dir=Directory(path); print(dir.path); //Volumes/coder/Project/Flutter/flutter_journey/lib/day6/data print(Directory.current.path); / / the current Project disk path: / Volumes/coder/Project/Flutter/flutter_journey print (dir. Absolute. Path); //Volumes/coder/Project/Flutter/flutter_journey/lib/day6/data dir.createTemp("-"); // Randomly create a folder with custom prefixes, dir.list(recursive: true).foreach ((e){print(e.path); }). Then ((v){print(" run "); }); print("----"); // Verify that the list method is asynchronousCopy the code
File API for basic operations
  • File operation correlation
-- -- -- - > [asynchronous operations] -- the Future < File > create ({bool recursive: false}); Future<File> rename(String newPath); // Asynchronously rename the File Future<File> copy(String newPath); Future<RandomAccessFile> open({FileMode mode: filemode.read}); ----> ---- void createSync({bool recursive: false}); // create a File synchronously (recursive or not) File renameSync(String newPath); File copySync(String newPath); RandomAccessFile openSync({FileMode mode: filemode.read}); // Open the file synchronouslyCopy the code

I don’t know if it’s acceptable to abbreviate it like this, but this is a chain call to a Future object

You can see that create is still returning a Future object, which means that the then callback is still a File object and you can continue to call the corresponding asynchronous method and then, and then, and then, and then, isn’t that interesting?

Var path = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / data/dragon. TXT'; Var pathCopy = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / data/should be dragon - copy. TXT'; Var pathRename = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / data/should be dragon - rename. TXT'; var file = File(path); file .create(recursive: True).then((file)=> file.copy(pathCopy).then((file)=> file.rename(pathRename).then((file)=>print(" create, copy, rename complete "))));Copy the code

  • File information correlation

There’s nothing to be said for this group, as the name suggests, just know that there are apis when you need them, right

----> ---- Future<int> length(); Future<DateTime> lastemail exchange (); Future setLastemail exchange (DateTime time); Future<DateTime> lastModified(); Future setLastModified(DateTime time); ---->[synchronous operation]---- int lengthSync(); DateTime lastAccessedSync(); Void setLastAccessedSync(DateTime time); DateTime lastModifiedSync(); Void setLastModifiedSync(DateTime time); // Set the last modification time File get absolute; // Get absolute file String get path; Directory get parent => new Directory(parentOf(path)); // Get the parent fileCopy the code
  • File read and write correlation

Reading and writing files is of Paramount importance

IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8}); ---->[asynchronous write]---- Future<File> writeAsBytes(List<int> bytes, {FileMode mode: filemode. write, bool Flush: false}); Future<File> writeAsString(String contents, {FileMode mode: FileMode.write,Encoding encoding: utf8,bool flush: false}); ---->[synchronous write operation]---- void writeAsBytesSync(List<int> bytes, {FileMode mode: filemode. write, bool Flush: false}); void writeAsStringSync(String contents, {FileMode mode: FileMode.write,Encoding encoding: utf8,bool flush: false}); Stream<List<int>> openRead([int start, int end]); -- -- -- - > [asynchronous read operation] -- the Future < List < int > > readAsBytes (); Future<String> readAsString({Encoding encoding: utf8}); Future<List<String>> readAsLines({Encoding encoding: utf8}); ----> ---- List<int> readAsBytesSync(); String readAsStringSync({Encoding encoding: utf8}); List<String> readAsLinesSync({Encoding encoding: utf8});Copy the code

File reading and writing
  • OpenWrite method

One, it returns an IOSink object; Second, it takes mode and code as input parameters

Here we test it. It automatically creates files and writes characters. Note that it does not automatically create folders

Var path = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / data/should be dragon - openWrite. TXT'; var file=File(path); File. OpenWrite (.) write (" should be dragon ");Copy the code

The IOSink object returned has several methods that can write to different types, such as arrays

You can customize the delimiter at write time

var li=["Java","Dart","Kotlin","Swift"]; File. OpenWrite (.) writeAll (li, "xx"); ---->[result]---- Java¥Dart¥Kotlin¥SwiftCopy the code

  • About the read mode

The default value is filemode. write. The name is written with the original content empty.

Filemode. write// Open the read/write file, it will overwrite the existing file filemode. append// Open the read/write file, append filemode. writeOnly// Open the write only file, Will overwrite existing files FileMode. WriteOnlyAppend / / open only to write file, add backCopy the code

File read operations

OpenRead returns a Stream<List> object, which, like Future, has a listen callback method

It can call back a sequence of future objects, and if you test it, it’s also asynchronous and it’s calling back a List, which is the set of values of the corresponding byte in the code table.

Var path = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / data/should be dragon - openRead. TXT'; file.openRead().listen((li) => li.forEach((e) => print(String.fromCharCode(e))));Copy the code

You can see that there are two indeterminate parameters in the openRead method that control where the read starts and stops

As for why this works: If a very large file passes through readAsString, it will be loaded into memory at once and will crash if it runs out of memory. The Stream is like a long Stream, read bit by bit.

Var path = '/ Volumes/coder/Project/Flutter/flutter_journey/lib/day6 / data/should be dragon - openRead. TXT'; file.openRead().listen((li) => li.forEach((e) => print(String.fromCharCode(e))));Copy the code

Some other methods, the use of the same, will not be repeated.


conclusion

This is the end of this article. If you want to taste Flutter quickly, Flutter For Seven days is a must-have. If you want to explore it, follow in my footsteps and complete a Flutter tour. In addition, I have a Flutter wechat communication group. You are welcome to join and discuss Flutter issues together. My wechat account is ZDL1994328.