核心库导览
This page shows you how to use the major features in Dart’s core libraries. It’s just an overview, and by no means comprehensive. Whenever you need more details about a class, consult the Dart API reference.
- dart:core
- Built-in types, collections, and other core functionality. This library is automatically imported into every Dart program.
- dart:async
- Support for asynchronous programming, with classes such as Future and Stream.
- dart:math
- Mathematical constants and functions, plus a random number generator.
- dart:convert
- Encoders and decoders for converting between different data representations, including JSON and UTF-8.
- dart:html
- DOM and other APIs for browser-based apps.
- dart:io
- I/O for programs that can use the Dart VM, including Flutter apps, servers, and command-line scripts.
This page is just an overview; it covers only a few dart:* libraries and no third-party libraries.
Other places to find library information are the Pub site and the Dart web developer library guide. You can find API documentation for all dart:* libraries in the Dart API reference or, if you’re using Flutter, the Flutter API reference.
dart:core – 数值、集合、字符串及更多
The dart:core library (API reference) provides a small but critical set of built-in functionality. This library is automatically imported into every Dart program.
Printing to the console
The top-level print()
method takes a single argument (any Object) and displays that object’s string value (as returned by toString()
) in the console.
1 2 |
<span class="pln">print</span><span class="pun">(</span><span class="pln">anObject</span><span class="pun">);</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'I drink $tea.'</span><span class="pun">);</span> |
For more information on basic strings and toString()
, see Strings in the language tour.
Numbers
The dart:core library defines the num, int, and double classes, which have some basic utilities for working with numbers.
You can convert a string into an integer or double with the parse()
methods of int and double, respectively:
1 2 3 |
<span class="kwd">assert</span><span class="pun">(</span><span class="typ">int</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'42'</span><span class="pun">)</span> <span class="pun">==</span> <span class="lit">42</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="typ">int</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'0x42'</span><span class="pun">)</span> <span class="pun">==</span> <span class="lit">66</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="typ">double</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'0.50'</span><span class="pun">)</span> <span class="pun">==</span> <span class="lit">0.5</span><span class="pun">);</span> |
Or use the parse() method of num, which creates an integer if possible and otherwise a double:
1 2 3 |
<span class="kwd">assert</span><span class="pun">(</span><span class="typ">num</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'42'</span><span class="pun">)</span> <span class="kwd">is</span> <span class="typ">int</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="typ">num</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'0x42'</span><span class="pun">)</span> <span class="kwd">is</span> <span class="typ">int</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="typ">num</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'0.50'</span><span class="pun">)</span> <span class="kwd">is</span> <span class="typ">double</span><span class="pun">);</span> |
To specify the base of an integer, add a radix
parameter:
1 |
<span class="kwd">assert</span><span class="pun">(</span><span class="typ">int</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'42'</span><span class="pun">,</span><span class="pln"> radix</span><span class="pun">:</span> <span class="lit">16</span><span class="pun">)</span> <span class="pun">==</span> <span class="lit">66</span><span class="pun">);</span> |
Use the toString()
method to convert an int or double to a string. To specify the number of digits to the right of the decimal, use toStringAsFixed(). To specify the number of significant digits in the string, use toStringAsPrecision():
1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="com">// Convert an int to a string.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="lit">42.</span><span class="pln">toString</span><span class="pun">()</span> <span class="pun">==</span> <span class="str">'42'</span><span class="pun">);</span> <span class="com">// Convert a double to a string.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="lit">123.456</span><span class="pun">.</span><span class="pln">toString</span><span class="pun">()</span> <span class="pun">==</span> <span class="str">'123.456'</span><span class="pun">);</span> <span class="com">// Specify the number of digits after the decimal.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="lit">123.456</span><span class="pun">.</span><span class="pln">toStringAsFixed</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span> <span class="pun">==</span> <span class="str">'123.46'</span><span class="pun">);</span> <span class="com">// Specify the number of significant figures.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="lit">123.456</span><span class="pun">.</span><span class="pln">toStringAsPrecision</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span> <span class="pun">==</span> <span class="str">'1.2e+2'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="typ">double</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'1.2e+2'</span><span class="pun">)</span> <span class="pun">==</span> <span class="lit">120.0</span><span class="pun">);</span> |
For more information, see the API documentation for int, double, and num. Also see the dart:math section.
Strings and regular expressions
A string in Dart is an immutable sequence of UTF-16 code units. The language tour has more information about strings. You can use regular expressions (RegExp objects) to search within strings and to replace parts of strings.
The String class defines such methods as split()
, contains()
, startsWith()
, endsWith()
, and more.
Searching inside a string
You can find particular locations within a string, as well as check whether a string begins with or ends with a particular pattern. For example:
1 2 3 4 5 6 7 8 9 10 11 |
<span class="com">// Check whether a string contains another string.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">'Never odd or even'</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="str">'odd'</span><span class="pun">));</span> <span class="com">// Does a string start with another string?</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">'Never odd or even'</span><span class="pun">.</span><span class="pln">startsWith</span><span class="pun">(</span><span class="str">'Never'</span><span class="pun">));</span> <span class="com">// Does a string end with another string?</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">'Never odd or even'</span><span class="pun">.</span><span class="pln">endsWith</span><span class="pun">(</span><span class="str">'even'</span><span class="pun">));</span> <span class="com">// Find the location of a string inside a string.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">'Never odd or even'</span><span class="pun">.</span><span class="pln">indexOf</span><span class="pun">(</span><span class="str">'odd'</span><span class="pun">)</span> <span class="pun">==</span> <span class="lit">6</span><span class="pun">);</span> |
从字符串中提取数据
You can get the individual characters from a string as Strings or ints, respectively. To be precise, you actually get individual UTF-16 code units; high-numbered characters such as the treble clef symbol (‘\u{1D11E}’) are two code units apiece.
You can also extract a substring or split a string into a list of substrings:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<span class="com">// Grab a substring.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">'Never odd or even'</span><span class="pun">.</span><span class="pln">substring</span><span class="pun">(</span><span class="lit">6</span><span class="pun">,</span> <span class="lit">9</span><span class="pun">)</span> <span class="pun">==</span> <span class="str">'odd'</span><span class="pun">);</span> <span class="com">// Split a string using a string pattern.</span> <span class="kwd">var</span><span class="pln"> parts </span><span class="pun">=</span> <span class="str">'structured web apps'</span><span class="pun">.</span><span class="pln">split</span><span class="pun">(</span><span class="str">' '</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">parts</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">3</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">parts</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span> <span class="pun">==</span> <span class="str">'structured'</span><span class="pun">);</span> <span class="com">// Get a UTF-16 code unit (as a string) by index.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">'Never odd or even'</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span> <span class="pun">==</span> <span class="str">'N'</span><span class="pun">);</span> <span class="com">// Use split() with an empty string parameter to get</span> <span class="com">// a list of all characters (as Strings); good for</span> <span class="com">// iterating.</span> <span class="kwd">for</span> <span class="pun">(</span><span class="kwd">var</span><span class="pln"> char </span><span class="kwd">in</span> <span class="str">'hello'</span><span class="pun">.</span><span class="pln">split</span><span class="pun">(</span><span class="str">''</span><span class="pun">))</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">char</span><span class="pun">);</span> <span class="pun">}</span> <span class="com">// Get all the UTF-16 code units in the string.</span> <span class="kwd">var</span><span class="pln"> codeUnitList </span><span class="pun">=</span> <span class="str">'Never odd or even'</span><span class="pun">.</span><span class="pln">codeUnits</span><span class="pun">.</span><span class="pln">toList</span><span class="pun">();</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">codeUnitList</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span> <span class="pun">==</span> <span class="lit">78</span><span class="pun">);</span> |
转换为大写或小写
You can easily convert strings to their uppercase and lowercase variants:
1 2 3 4 5 6 7 |
<span class="com">// Convert to uppercase.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">'structured web apps'</span><span class="pun">.</span><span class="pln">toUpperCase</span><span class="pun">()</span> <span class="pun">==</span> <span class="str">'STRUCTURED WEB APPS'</span><span class="pun">);</span> <span class="com">// Convert to lowercase.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">'STRUCTURED WEB APPS'</span><span class="pun">.</span><span class="pln">toLowerCase</span><span class="pun">()</span> <span class="pun">==</span> <span class="str">'structured web apps'</span><span class="pun">);</span> |
Note: These methods don’t work for every language. For example, the Turkish alphabet’s dotless I is converted incorrectly.
Trimming and empty strings
Remove all leading and trailing white space with trim()
. To check whether a string is empty (length is zero), use isEmpty
.
1 2 3 4 5 6 7 8 |
<span class="com">// Trim a string.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">' hello '</span><span class="pun">.</span><span class="pln">trim</span><span class="pun">()</span> <span class="pun">==</span> <span class="str">'hello'</span><span class="pun">);</span> <span class="com">// Check whether a string is empty.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">''</span><span class="pun">.</span><span class="pln">isEmpty</span><span class="pun">);</span> <span class="com">// Strings with only white space are not empty.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="str">' '</span><span class="pun">.</span><span class="pln">isNotEmpty</span><span class="pun">);</span> |
Replacing part of a string
Strings are immutable objects, which means you can create them but you can’t change them. If you look closely at the String API reference, you’ll notice that none of the methods actually changes the state of a String. For example, the method replaceAll()
returns a new String without changing the original String:
1 2 3 4 5 6 |
<span class="kwd">var</span><span class="pln"> greetingTemplate </span><span class="pun">=</span> <span class="str">'Hello, NAME!'</span><span class="pun">;</span> <span class="kwd">var</span><span class="pln"> greeting </span><span class="pun">=</span><span class="pln"> greetingTemplate</span><span class="pun">.</span><span class="pln">replaceAll</span><span class="pun">(</span><span class="typ">RegExp</span><span class="pun">(</span><span class="str">'NAME'</span><span class="pun">),</span> <span class="str">'Bob'</span><span class="pun">);</span> <span class="com">// greetingTemplate didn't change.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">greeting </span><span class="pun">!=</span><span class="pln"> greetingTemplate</span><span class="pun">);</span> |
构建字符串
To programmatically generate a string, you can use StringBuffer. A StringBuffer doesn’t generate a new String object until toString()
is called. The writeAll()
method has an optional second parameter that lets you specify a separator—in this case, a space.
1 2 3 4 5 6 7 8 9 10 |
<span class="kwd">var</span><span class="pln"> sb </span><span class="pun">=</span> <span class="typ">StringBuffer</span><span class="pun">();</span><span class="pln"> sb </span><span class="pun">..</span><span class="pln">write</span><span class="pun">(</span><span class="str">'Use a StringBuffer for '</span><span class="pun">)</span> <span class="pun">..</span><span class="pln">writeAll</span><span class="pun">([</span><span class="str">'efficient'</span><span class="pun">,</span> <span class="str">'string'</span><span class="pun">,</span> <span class="str">'creation'</span><span class="pun">],</span> <span class="str">' '</span><span class="pun">)</span> <span class="pun">..</span><span class="pln">write</span><span class="pun">(</span><span class="str">'.'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> fullString </span><span class="pun">=</span><span class="pln"> sb</span><span class="pun">.</span><span class="pln">toString</span><span class="pun">();</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">fullString </span><span class="pun">==</span> <span class="str">'Use a StringBuffer for efficient string creation.'</span><span class="pun">);</span> |
正则表达式
The RegExp class provides the same capabilities as JavaScript regular expressions. Use regular expressions for efficient searching and pattern matching of strings.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="com">// Here's a regular expression for one or more digits.</span> <span class="kwd">var</span><span class="pln"> numbers </span><span class="pun">=</span> <span class="typ">RegExp</span><span class="pun">(</span><span class="str">r'\d+'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> allCharacters </span><span class="pun">=</span> <span class="str">'llamas live fifteen to twenty years'</span><span class="pun">;</span> <span class="kwd">var</span><span class="pln"> someDigits </span><span class="pun">=</span> <span class="str">'llamas live 15 to 20 years'</span><span class="pun">;</span> <span class="com">// contains() can use a regular expression.</span> <span class="kwd">assert</span><span class="pun">(!</span><span class="pln">allCharacters</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="pln">numbers</span><span class="pun">));</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">someDigits</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="pln">numbers</span><span class="pun">));</span> <span class="com">// Replace every match with another string.</span> <span class="kwd">var</span><span class="pln"> exedOut </span><span class="pun">=</span><span class="pln"> someDigits</span><span class="pun">.</span><span class="pln">replaceAll</span><span class="pun">(</span><span class="pln">numbers</span><span class="pun">,</span> <span class="str">'XX'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">exedOut </span><span class="pun">==</span> <span class="str">'llamas live XX to XX years'</span><span class="pun">);</span> |
You can work directly with the RegExp class, too. The Match class provides access to a regular expression match.
1 2 3 4 5 6 7 8 9 10 |
<span class="kwd">var</span><span class="pln"> numbers </span><span class="pun">=</span> <span class="typ">RegExp</span><span class="pun">(</span><span class="str">r'\d+'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> someDigits </span><span class="pun">=</span> <span class="str">'llamas live 15 to 20 years'</span><span class="pun">;</span> <span class="com">// Check whether the reg exp has a match in a string.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">numbers</span><span class="pun">.</span><span class="pln">hasMatch</span><span class="pun">(</span><span class="pln">someDigits</span><span class="pun">));</span> <span class="com">// Loop through all matches.</span> <span class="kwd">for</span> <span class="pun">(</span><span class="kwd">var</span><span class="pln"> match </span><span class="kwd">in</span><span class="pln"> numbers</span><span class="pun">.</span><span class="pln">allMatches</span><span class="pun">(</span><span class="pln">someDigits</span><span class="pun">))</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">match</span><span class="pun">.</span><span class="pln">group</span><span class="pun">(</span><span class="lit">0</span><span class="pun">));</span> <span class="com">// 15, then 20</span> <span class="pun">}</span> |
More information
Refer to the String API reference for a full list of methods. Also see the API reference for StringBuffer, Pattern, RegExp, and Match.
集合
Dart ships with a core collections API, which includes classes for lists, sets, and maps.
列表
As the language tour shows, you can use literals to create and initialize lists. Alternatively, use one of the List constructors. The List class also defines several methods for adding items to and removing items from lists.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span class="com">// Use a List constructor.</span> <span class="kwd">var</span><span class="pln"> vegetables </span><span class="pun">=</span> <span class="typ">List</span><span class="pun">();</span> <span class="com">// Or simply use a list literal.</span> <span class="kwd">var</span><span class="pln"> fruits </span><span class="pun">=</span> <span class="pun">[</span><span class="str">'apples'</span><span class="pun">,</span> <span class="str">'oranges'</span><span class="pun">];</span> <span class="com">// Add to a list.</span><span class="pln"> fruits</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="str">'kiwis'</span><span class="pun">);</span> <span class="com">// Add multiple items to a list.</span><span class="pln"> fruits</span><span class="pun">.</span><span class="pln">addAll</span><span class="pun">([</span><span class="str">'grapes'</span><span class="pun">,</span> <span class="str">'bananas'</span><span class="pun">]);</span> <span class="com">// Get the list length.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">5</span><span class="pun">);</span> <span class="com">// Remove a single item.</span> <span class="kwd">var</span><span class="pln"> appleIndex </span><span class="pun">=</span><span class="pln"> fruits</span><span class="pun">.</span><span class="pln">indexOf</span><span class="pun">(</span><span class="str">'apples'</span><span class="pun">);</span><span class="pln"> fruits</span><span class="pun">.</span><span class="pln">removeAt</span><span class="pun">(</span><span class="pln">appleIndex</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">4</span><span class="pun">);</span> <span class="com">// Remove all elements from a list.</span><span class="pln"> fruits</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">();</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">.</span><span class="pln">isEmpty</span><span class="pun">);</span> |
Use indexOf()
to find the index of an object in a list:
1 2 3 4 5 6 7 |
<span class="kwd">var</span><span class="pln"> fruits </span><span class="pun">=</span> <span class="pun">[</span><span class="str">'apples'</span><span class="pun">,</span> <span class="str">'oranges'</span><span class="pun">];</span> <span class="com">// Access a list item by index.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span> <span class="pun">==</span> <span class="str">'apples'</span><span class="pun">);</span> <span class="com">// Find an item in a list.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">.</span><span class="pln">indexOf</span><span class="pun">(</span><span class="str">'apples'</span><span class="pun">)</span> <span class="pun">==</span> <span class="lit">0</span><span class="pun">);</span> |
Sort a list using the sort()
method. You can provide a sorting function that compares two objects. This sorting function must return < 0 for smaller, 0 for the same, and > 0 for bigger. The following example uses compareTo()
, which is defined by Comparable and implemented by String.
1 2 3 4 5 |
<span class="kwd">var</span><span class="pln"> fruits </span><span class="pun">=</span> <span class="pun">[</span><span class="str">'bananas'</span><span class="pun">,</span> <span class="str">'apples'</span><span class="pun">,</span> <span class="str">'oranges'</span><span class="pun">];</span> <span class="com">// Sort a list.</span><span class="pln"> fruits</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">((</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> a</span><span class="pun">.</span><span class="pln">compareTo</span><span class="pun">(</span><span class="pln">b</span><span class="pun">));</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span> <span class="pun">==</span> <span class="str">'apples'</span><span class="pun">);</span> |
Lists are parameterized types, so you can specify the type that a list should contain:
1 2 3 4 5 6 |
<span class="com">// This list should contain only strings.</span> <span class="kwd">var</span><span class="pln"> fruits </span><span class="pun">=</span> <span class="typ">List</span><span class="pun"><</span><span class="typ">String</span><span class="pun">>();</span><span class="pln"> fruits</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="str">'apples'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> fruit </span><span class="pun">=</span><span class="pln"> fruits</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">fruit </span><span class="kwd">is</span> <span class="typ">String</span><span class="pun">);</span> |
1 |
<span class="pln">fruits</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span> <span class="com">// Error: 'int' can't be assigned to 'String'</span> |
Refer to the List API reference for a full list of methods.
集
A set in Dart is an unordered collection of unique items. Because a set is unordered, you can’t get a set’s items by index (position).
1 2 3 4 5 6 7 8 9 10 11 |
<span class="kwd">var</span><span class="pln"> ingredients </span><span class="pun">=</span> <span class="kwd">Set</span><span class="pun">();</span><span class="pln"> ingredients</span><span class="pun">.</span><span class="pln">addAll</span><span class="pun">([</span><span class="str">'gold'</span><span class="pun">,</span> <span class="str">'titanium'</span><span class="pun">,</span> <span class="str">'xenon'</span><span class="pun">]);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">ingredients</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">3</span><span class="pun">);</span> <span class="com">// Adding a duplicate item has no effect.</span><span class="pln"> ingredients</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="str">'gold'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">ingredients</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">3</span><span class="pun">);</span> <span class="com">// Remove an item from a set.</span><span class="pln"> ingredients</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="str">'gold'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">ingredients</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">2</span><span class="pun">);</span> |
Use contains()
and containsAll()
to check whether one or more objects are in a set:
1 2 3 4 5 6 7 8 |
<span class="kwd">var</span><span class="pln"> ingredients </span><span class="pun">=</span> <span class="kwd">Set</span><span class="pun">();</span><span class="pln"> ingredients</span><span class="pun">.</span><span class="pln">addAll</span><span class="pun">([</span><span class="str">'gold'</span><span class="pun">,</span> <span class="str">'titanium'</span><span class="pun">,</span> <span class="str">'xenon'</span><span class="pun">]);</span> <span class="com">// Check whether an item is in the set.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">ingredients</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="str">'titanium'</span><span class="pun">));</span> <span class="com">// Check whether all the items are in the set.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">ingredients</span><span class="pun">.</span><span class="pln">containsAll</span><span class="pun">([</span><span class="str">'titanium'</span><span class="pun">,</span> <span class="str">'xenon'</span><span class="pun">]));</span> |
An intersection is a set whose items are in two other sets.
1 2 3 4 5 6 7 8 |
<span class="kwd">var</span><span class="pln"> ingredients </span><span class="pun">=</span> <span class="kwd">Set</span><span class="pun">();</span><span class="pln"> ingredients</span><span class="pun">.</span><span class="pln">addAll</span><span class="pun">([</span><span class="str">'gold'</span><span class="pun">,</span> <span class="str">'titanium'</span><span class="pun">,</span> <span class="str">'xenon'</span><span class="pun">]);</span> <span class="com">// Create the intersection of two sets.</span> <span class="kwd">var</span><span class="pln"> nobleGases </span><span class="pun">=</span> <span class="kwd">Set</span><span class="pun">.</span><span class="pln">from</span><span class="pun">([</span><span class="str">'xenon'</span><span class="pun">,</span> <span class="str">'argon'</span><span class="pun">]);</span> <span class="kwd">var</span><span class="pln"> intersection </span><span class="pun">=</span><span class="pln"> ingredients</span><span class="pun">.</span><span class="pln">intersection</span><span class="pun">(</span><span class="pln">nobleGases</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">intersection</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">1</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">intersection</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="str">'xenon'</span><span class="pun">));</span> |
Refer to the Set API reference for a full list of methods.
Maps
A map, commonly known as a dictionary or hash, is an unordered collection of key-value pairs. Maps associate a key to some value for easy retrieval. Unlike in JavaScript, Dart objects are not maps.
You can declare a map using a terse literal syntax, or you can use a traditional constructor:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="com">// Maps often use strings as keys.</span> <span class="kwd">var</span><span class="pln"> hawaiianBeaches </span><span class="pun">=</span> <span class="pun">{</span> <span class="str">'Oahu'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Waikiki'</span><span class="pun">,</span> <span class="str">'Kailua'</span><span class="pun">,</span> <span class="str">'Waimanalo'</span><span class="pun">],</span> <span class="str">'Big Island'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Wailea Bay'</span><span class="pun">,</span> <span class="str">'Pololu Beach'</span><span class="pun">],</span> <span class="str">'Kauai'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Hanalei'</span><span class="pun">,</span> <span class="str">'Poipu'</span><span class="pun">]</span> <span class="pun">};</span> <span class="com">// Maps can be built from a constructor.</span> <span class="kwd">var</span><span class="pln"> searchTerms </span><span class="pun">=</span> <span class="typ">Map</span><span class="pun">();</span> <span class="com">// Maps are parameterized types; you can specify what</span> <span class="com">// types the key and value should be.</span> <span class="kwd">var</span><span class="pln"> nobleGases </span><span class="pun">=</span> <span class="typ">Map</span><span class="pun"><</span><span class="typ">int</span><span class="pun">,</span> <span class="typ">String</span><span class="pun">>();</span> |
You add, get, and set map items using the bracket syntax. Use remove()
to remove a key and its value from a map.
1 2 3 4 5 6 7 8 9 10 11 |
<span class="kwd">var</span><span class="pln"> nobleGases </span><span class="pun">=</span> <span class="pun">{</span><span class="lit">54</span><span class="pun">:</span> <span class="str">'xenon'</span><span class="pun">};</span> <span class="com">// Retrieve a value with a key.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">nobleGases</span><span class="pun">[</span><span class="lit">54</span><span class="pun">]</span> <span class="pun">==</span> <span class="str">'xenon'</span><span class="pun">);</span> <span class="com">// Check whether a map contains a key.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">nobleGases</span><span class="pun">.</span><span class="pln">containsKey</span><span class="pun">(</span><span class="lit">54</span><span class="pun">));</span> <span class="com">// Remove a key and its value.</span><span class="pln"> nobleGases</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="lit">54</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(!</span><span class="pln">nobleGases</span><span class="pun">.</span><span class="pln">containsKey</span><span class="pun">(</span><span class="lit">54</span><span class="pun">));</span> |
You can retrieve all the values or all the keys from a map:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="kwd">var</span><span class="pln"> hawaiianBeaches </span><span class="pun">=</span> <span class="pun">{</span> <span class="str">'Oahu'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Waikiki'</span><span class="pun">,</span> <span class="str">'Kailua'</span><span class="pun">,</span> <span class="str">'Waimanalo'</span><span class="pun">],</span> <span class="str">'Big Island'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Wailea Bay'</span><span class="pun">,</span> <span class="str">'Pololu Beach'</span><span class="pun">],</span> <span class="str">'Kauai'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Hanalei'</span><span class="pun">,</span> <span class="str">'Poipu'</span><span class="pun">]</span> <span class="pun">};</span> <span class="com">// Get all the keys as an unordered collection</span> <span class="com">// (an Iterable).</span> <span class="kwd">var</span><span class="pln"> keys </span><span class="pun">=</span><span class="pln"> hawaiianBeaches</span><span class="pun">.</span><span class="pln">keys</span><span class="pun">;</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">keys</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">3</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="kwd">Set</span><span class="pun">.</span><span class="pln">from</span><span class="pun">(</span><span class="pln">keys</span><span class="pun">).</span><span class="pln">contains</span><span class="pun">(</span><span class="str">'Oahu'</span><span class="pun">));</span> <span class="com">// Get all the values as an unordered collection</span> <span class="com">// (an Iterable of Lists).</span> <span class="kwd">var</span><span class="pln"> values </span><span class="pun">=</span><span class="pln"> hawaiianBeaches</span><span class="pun">.</span><span class="pln">values</span><span class="pun">;</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">values</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span> <span class="lit">3</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">values</span><span class="pun">.</span><span class="pln">any</span><span class="pun">((</span><span class="pln">v</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> v</span><span class="pun">.</span><span class="pln">contains</span><span class="pun">(</span><span class="str">'Waikiki'</span><span class="pun">)));</span> |
To check whether a map contains a key, use containsKey()
. Because map values can be null, you cannot rely on simply getting the value for the key and checking for null to determine the existence of a key.
1 2 3 4 5 6 7 8 |
<span class="kwd">var</span><span class="pln"> hawaiianBeaches </span><span class="pun">=</span> <span class="pun">{</span> <span class="str">'Oahu'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Waikiki'</span><span class="pun">,</span> <span class="str">'Kailua'</span><span class="pun">,</span> <span class="str">'Waimanalo'</span><span class="pun">],</span> <span class="str">'Big Island'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Wailea Bay'</span><span class="pun">,</span> <span class="str">'Pololu Beach'</span><span class="pun">],</span> <span class="str">'Kauai'</span><span class="pun">:</span> <span class="pun">[</span><span class="str">'Hanalei'</span><span class="pun">,</span> <span class="str">'Poipu'</span><span class="pun">]</span> <span class="pun">};</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">hawaiianBeaches</span><span class="pun">.</span><span class="pln">containsKey</span><span class="pun">(</span><span class="str">'Oahu'</span><span class="pun">));</span> <span class="kwd">assert</span><span class="pun">(!</span><span class="pln">hawaiianBeaches</span><span class="pun">.</span><span class="pln">containsKey</span><span class="pun">(</span><span class="str">'Florida'</span><span class="pun">));</span> |
Use the putIfAbsent()
method when you want to assign a value to a key if and only if the key does not already exist in a map. You must provide a function that returns the value.
1 2 3 4 |
<span class="kwd">var</span><span class="pln"> teamAssignments </span><span class="pun">=</span> <span class="pun">{};</span><span class="pln"> teamAssignments</span><span class="pun">.</span><span class="pln">putIfAbsent</span><span class="pun">(</span> <span class="str">'Catcher'</span><span class="pun">,</span> <span class="pun">()</span> <span class="pun">=></span><span class="pln"> pickToughestKid</span><span class="pun">());</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">teamAssignments</span><span class="pun">[</span><span class="str">'Catcher'</span><span class="pun">]</span> <span class="pun">!=</span> <span class="kwd">null</span><span class="pun">);</span> |
Refer to the Map API reference for a full list of methods.
Common collection methods
List, Set, and Map share common functionality found in many collections. Some of this common functionality is defined by the Iterable class, which List and Set implement.
Note: Although Map doesn’t implement Iterable, you can get Iterables from it using the Map keys
and values
properties.
Use isEmpty
or isNotEmpty
to check whether a list, set, or map has items:
1 2 3 4 |
<span class="kwd">var</span><span class="pln"> coffees </span><span class="pun">=</span> <span class="pun">[];</span> <span class="kwd">var</span><span class="pln"> teas </span><span class="pun">=</span> <span class="pun">[</span><span class="str">'green'</span><span class="pun">,</span> <span class="str">'black'</span><span class="pun">,</span> <span class="str">'chamomile'</span><span class="pun">,</span> <span class="str">'earl grey'</span><span class="pun">];</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">coffees</span><span class="pun">.</span><span class="pln">isEmpty</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">teas</span><span class="pun">.</span><span class="pln">isNotEmpty</span><span class="pun">);</span> |
To apply a function to each item in a list, set, or map, you can use forEach()
:
1 2 3 |
<span class="kwd">var</span><span class="pln"> teas </span><span class="pun">=</span> <span class="pun">[</span><span class="str">'green'</span><span class="pun">,</span> <span class="str">'black'</span><span class="pun">,</span> <span class="str">'chamomile'</span><span class="pun">,</span> <span class="str">'earl grey'</span><span class="pun">];</span><span class="pln"> teas</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">((</span><span class="pln">tea</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> print</span><span class="pun">(</span><span class="str">'I drink $tea'</span><span class="pun">));</span> |
When you invoke forEach()
on a map, your function must take two arguments (the key and value):
1 2 3 4 5 |
<span class="pln">hawaiianBeaches</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">((</span><span class="pln">k</span><span class="pun">,</span><span class="pln"> v</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'I want to visit $k and swim at $v'</span><span class="pun">);</span> <span class="com">// I want to visit Oahu and swim at</span> <span class="com">// [Waikiki, Kailua, Waimanalo], etc.</span> <span class="pun">});</span> |
Iterables provide the map()
method, which gives you all the results in a single object:
1 2 3 4 |
<span class="kwd">var</span><span class="pln"> teas </span><span class="pun">=</span> <span class="pun">[</span><span class="str">'green'</span><span class="pun">,</span> <span class="str">'black'</span><span class="pun">,</span> <span class="str">'chamomile'</span><span class="pun">,</span> <span class="str">'earl grey'</span><span class="pun">];</span> <span class="kwd">var</span><span class="pln"> loudTeas </span><span class="pun">=</span><span class="pln"> teas</span><span class="pun">.</span><span class="pln">map</span><span class="pun">((</span><span class="pln">tea</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> tea</span><span class="pun">.</span><span class="pln">toUpperCase</span><span class="pun">());</span><span class="pln"> loudTeas</span><span class="pun">.</span><span class="pln">forEach</span><span class="pun">(</span><span class="pln">print</span><span class="pun">);</span> |
Note: The object returned by map()
is an Iterable that’s lazily evaluated: your function isn’t called until you ask for an item from the returned object.
To force your function to be called immediately on each item, use map().toList()
or map().toSet()
:
1 2 |
<span class="kwd">var</span><span class="pln"> loudTeas </span><span class="pun">=</span><span class="pln"> teas</span><span class="pun">.</span><span class="pln">map</span><span class="pun">((</span><span class="pln">tea</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> tea</span><span class="pun">.</span><span class="pln">toUpperCase</span><span class="pun">()).</span><span class="pln">toList</span><span class="pun">();</span> |
Use Iterable’s where()
method to get all the items that match a condition. Use Iterable’s any()
and every()
methods to check whether some or all items match a condition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span class="kwd">var</span><span class="pln"> teas </span><span class="pun">=</span> <span class="pun">[</span><span class="str">'green'</span><span class="pun">,</span> <span class="str">'black'</span><span class="pun">,</span> <span class="str">'chamomile'</span><span class="pun">,</span> <span class="str">'earl grey'</span><span class="pun">];</span> <span class="com">// Chamomile is not caffeinated.</span> <span class="typ">bool</span><span class="pln"> isDecaffeinated</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> teaName</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> teaName </span><span class="pun">==</span> <span class="str">'chamomile'</span><span class="pun">;</span> <span class="com">// Use where() to find only the items that return true</span> <span class="com">// from the provided function.</span> <span class="kwd">var</span><span class="pln"> decaffeinatedTeas </span><span class="pun">=</span><span class="pln"> teas</span><span class="pun">.</span><span class="pln">where</span><span class="pun">((</span><span class="pln">tea</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> isDecaffeinated</span><span class="pun">(</span><span class="pln">tea</span><span class="pun">));</span> <span class="com">// or teas.where(isDecaffeinated)</span> <span class="com">// Use any() to check whether at least one item in the</span> <span class="com">// collection satisfies a condition.</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">teas</span><span class="pun">.</span><span class="pln">any</span><span class="pun">(</span><span class="pln">isDecaffeinated</span><span class="pun">));</span> <span class="com">// Use every() to check whether all the items in a</span> <span class="com">// collection satisfy a condition.</span> <span class="kwd">assert</span><span class="pun">(!</span><span class="pln">teas</span><span class="pun">.</span><span class="pln">every</span><span class="pun">(</span><span class="pln">isDecaffeinated</span><span class="pun">));</span> |
For a full list of methods, refer to the Iterable API reference, as well as those for List, Set, and Map.
URIs
The Uri class provides functions to encode and decode strings for use in URIs (which you might know as URLs). These functions handle characters that are special for URIs, such as &
and =
. The Uri class also parses and exposes the components of a URI—host, port, scheme, and so on.
Encoding and decoding fully qualified URIs
To encode and decode characters except those with special meaning in a URI (such as /
, :
, &
, #
), use the encodeFull()
and decodeFull()
methods. These methods are good for encoding or decoding a fully qualified URI, leaving intact special URI characters.
1 2 3 4 5 6 7 8 |
<span class="kwd">var</span><span class="pln"> uri </span><span class="pun">=</span> <span class="str">'http://example.org/api?foo=some message'</span><span class="pun">;</span> <span class="kwd">var</span><span class="pln"> encoded </span><span class="pun">=</span> <span class="typ">Uri</span><span class="pun">.</span><span class="pln">encodeFull</span><span class="pun">(</span><span class="pln">uri</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">encoded </span><span class="pun">==</span> <span class="str">'http://example.org/api?foo=some%20message'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> decoded </span><span class="pun">=</span> <span class="typ">Uri</span><span class="pun">.</span><span class="pln">decodeFull</span><span class="pun">(</span><span class="pln">encoded</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">uri </span><span class="pun">==</span><span class="pln"> decoded</span><span class="pun">);</span> |
Notice how only the space between some
and message
was encoded.
Encoding and decoding URI components
To encode and decode all of a string’s characters that have special meaning in a URI, including (but not limited to) /
, &
, and :
, use the encodeComponent()
and decodeComponent()
methods.
1 2 3 4 5 6 7 8 |
<span class="kwd">var</span><span class="pln"> uri </span><span class="pun">=</span> <span class="str">'http://example.org/api?foo=some message'</span><span class="pun">;</span> <span class="kwd">var</span><span class="pln"> encoded </span><span class="pun">=</span> <span class="typ">Uri</span><span class="pun">.</span><span class="pln">encodeComponent</span><span class="pun">(</span><span class="pln">uri</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">encoded </span><span class="pun">==</span> <span class="str">'http%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> decoded </span><span class="pun">=</span> <span class="typ">Uri</span><span class="pun">.</span><span class="pln">decodeComponent</span><span class="pun">(</span><span class="pln">encoded</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">uri </span><span class="pun">==</span><span class="pln"> decoded</span><span class="pun">);</span> |
Notice how every special character is encoded. For example, /
is encoded to %2F
.
Parsing URIs
If you have a Uri object or a URI string, you can get its parts using Uri fields such as path
. To create a Uri from a string, use the parse()
static method:
1 2 3 4 5 6 7 8 |
<span class="kwd">var</span><span class="pln"> uri </span><span class="pun">=</span> <span class="typ">Uri</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'http://example.org:8080/foo/bar#frag'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">uri</span><span class="pun">.</span><span class="pln">scheme </span><span class="pun">==</span> <span class="str">'http'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">uri</span><span class="pun">.</span><span class="pln">host </span><span class="pun">==</span> <span class="str">'example.org'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">uri</span><span class="pun">.</span><span class="pln">path </span><span class="pun">==</span> <span class="str">'/foo/bar'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">uri</span><span class="pun">.</span><span class="pln">fragment </span><span class="pun">==</span> <span class="str">'frag'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">uri</span><span class="pun">.</span><span class="pln">origin </span><span class="pun">==</span> <span class="str">'http://example.org:8080'</span><span class="pun">);</span> |
See the Uri API reference for more URI components that you can get.
Building URIs
You can build up a URI from individual parts using the Uri()
constructor:
1 2 3 4 5 6 7 |
<span class="kwd">var</span><span class="pln"> uri </span><span class="pun">=</span> <span class="typ">Uri</span><span class="pun">(</span><span class="pln"> scheme</span><span class="pun">:</span> <span class="str">'http'</span><span class="pun">,</span><span class="pln"> host</span><span class="pun">:</span> <span class="str">'example.org'</span><span class="pun">,</span><span class="pln"> path</span><span class="pun">:</span> <span class="str">'/foo/bar'</span><span class="pun">,</span><span class="pln"> fragment</span><span class="pun">:</span> <span class="str">'frag'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln"> uri</span><span class="pun">.</span><span class="pln">toString</span><span class="pun">()</span> <span class="pun">==</span> <span class="str">'http://example.org/foo/bar#frag'</span><span class="pun">);</span> |
Dates and times
A DateTime object is a point in time. The time zone is either UTC or the local time zone.
You can create DateTime objects using several constructors:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="com">// Get the current date and time.</span> <span class="kwd">var</span><span class="pln"> now </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">.</span><span class="pln">now</span><span class="pun">();</span> <span class="com">// Create a new DateTime with the local time zone.</span> <span class="kwd">var</span><span class="pln"> y2k </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">(</span><span class="lit">2000</span><span class="pun">);</span> <span class="com">// January 1, 2000</span> <span class="com">// Specify the month and day.</span><span class="pln"> y2k </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">(</span><span class="lit">2000</span><span class="pun">,</span> <span class="lit">1</span><span class="pun">,</span> <span class="lit">2</span><span class="pun">);</span> <span class="com">// January 2, 2000</span> <span class="com">// Specify the date as a UTC time.</span><span class="pln"> y2k </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">.</span><span class="pln">utc</span><span class="pun">(</span><span class="lit">2000</span><span class="pun">);</span> <span class="com">// 1/1/2000, UTC</span> <span class="com">// Specify a date and time in ms since the Unix epoch.</span><span class="pln"> y2k </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">.</span><span class="pln">fromMillisecondsSinceEpoch</span><span class="pun">(</span><span class="lit">946684800000</span><span class="pun">,</span><span class="pln"> isUtc</span><span class="pun">:</span> <span class="kwd">true</span><span class="pun">);</span> <span class="com">// Parse an ISO 8601 date.</span><span class="pln"> y2k </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'2000-01-01T00:00:00Z'</span><span class="pun">);</span> |
The millisecondsSinceEpoch
property of a date returns the number of milliseconds since the “Unix epoch”—January 1, 1970, UTC:
1 2 3 4 5 6 7 |
<span class="com">// 1/1/2000, UTC</span> <span class="kwd">var</span><span class="pln"> y2k </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">.</span><span class="pln">utc</span><span class="pun">(</span><span class="lit">2000</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">y2k</span><span class="pun">.</span><span class="pln">millisecondsSinceEpoch </span><span class="pun">==</span> <span class="lit">946684800000</span><span class="pun">);</span> <span class="com">// 1/1/1970, UTC</span> <span class="kwd">var</span><span class="pln"> unixEpoch </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">.</span><span class="pln">utc</span><span class="pun">(</span><span class="lit">1970</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">unixEpoch</span><span class="pun">.</span><span class="pln">millisecondsSinceEpoch </span><span class="pun">==</span> <span class="lit">0</span><span class="pun">);</span> |
Use the Duration class to calculate the difference between two dates and to shift a date forward or backward:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span class="kwd">var</span><span class="pln"> y2k </span><span class="pun">=</span> <span class="typ">DateTime</span><span class="pun">.</span><span class="pln">utc</span><span class="pun">(</span><span class="lit">2000</span><span class="pun">);</span> <span class="com">// Add one year.</span> <span class="kwd">var</span><span class="pln"> y2001 </span><span class="pun">=</span><span class="pln"> y2k</span><span class="pun">.</span><span class="pln">add</span><span class="pun">(</span><span class="typ">Duration</span><span class="pun">(</span><span class="pln">days</span><span class="pun">:</span> <span class="lit">366</span><span class="pun">));</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">y2001</span><span class="pun">.</span><span class="pln">year </span><span class="pun">==</span> <span class="lit">2001</span><span class="pun">);</span> <span class="com">// Subtract 30 days.</span> <span class="kwd">var</span><span class="pln"> december2000 </span><span class="pun">=</span><span class="pln"> y2001</span><span class="pun">.</span><span class="pln">subtract</span><span class="pun">(</span><span class="typ">Duration</span><span class="pun">(</span><span class="pln">days</span><span class="pun">:</span> <span class="lit">30</span><span class="pun">));</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">december2000</span><span class="pun">.</span><span class="pln">year </span><span class="pun">==</span> <span class="lit">2000</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">december2000</span><span class="pun">.</span><span class="pln">month </span><span class="pun">==</span> <span class="lit">12</span><span class="pun">);</span> <span class="com">// Calculate the difference between two dates.</span> <span class="com">// Returns a Duration object.</span> <span class="kwd">var</span><span class="pln"> duration </span><span class="pun">=</span><span class="pln"> y2001</span><span class="pun">.</span><span class="pln">difference</span><span class="pun">(</span><span class="pln">y2k</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">duration</span><span class="pun">.</span><span class="pln">inDays </span><span class="pun">==</span> <span class="lit">366</span><span class="pun">);</span> <span class="com">// y2k was a leap year.</span> |
Warning: Using a Duration to shift a DateTime by days can be problematic, due to clock shifts (to daylight saving time, for example). Use UTC dates if you must shift days.
For a full list of methods, refer to the API reference for DateTime and Duration.
Utility classes
The core library contains various utility classes, useful for sorting, mapping values, and iterating.
Comparing objects
Implement the Comparable interface to indicate that an object can be compared to another object, usually for sorting. The compareTo()
method returns < 0 for smaller, 0 for the same, and > 0 for bigger.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="kwd">class</span> <span class="typ">Line</span> <span class="kwd">implements</span> <span class="typ">Comparable</span><span class="pun"><</span><span class="typ">Line</span><span class="pun">></span> <span class="pun">{</span> <span class="kwd">final</span> <span class="typ">int</span><span class="pln"> length</span><span class="pun">;</span> <span class="kwd">const</span> <span class="typ">Line</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">length</span><span class="pun">);</span><span class="pln"> @override </span><span class="typ">int</span><span class="pln"> compareTo</span><span class="pun">(</span><span class="typ">Line</span><span class="pln"> other</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> length </span><span class="pun">-</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">length</span><span class="pun">;</span> <span class="pun">}</span> <span class="typ">void</span><span class="pln"> main</span><span class="pun">()</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> short </span><span class="pun">=</span> <span class="kwd">const</span> <span class="typ">Line</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> long </span><span class="pun">=</span> <span class="kwd">const</span> <span class="typ">Line</span><span class="pun">(</span><span class="lit">100</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">short</span><span class="pun">.</span><span class="pln">compareTo</span><span class="pun">(</span><span class="pln">long</span><span class="pun">)</span> <span class="pun"><</span> <span class="lit">0</span><span class="pun">);</span> <span class="pun">}</span> |
Implementing map keys
Each object in Dart automatically provides an integer hash code, and thus can be used as a key in a map. However, you can override the hashCode
getter to generate a custom hash code. If you do, you might also want to override the ==
operator. Objects that are equal (via ==
) must have identical hash codes. A hash code doesn’t have to be unique, but it should be well distributed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<span class="kwd">class</span> <span class="typ">Person</span> <span class="pun">{</span> <span class="kwd">final</span> <span class="typ">String</span><span class="pln"> firstName</span><span class="pun">,</span><span class="pln"> lastName</span><span class="pun">;</span> <span class="typ">Person</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">firstName</span><span class="pun">,</span> <span class="kwd">this</span><span class="pun">.</span><span class="pln">lastName</span><span class="pun">);</span> <span class="com">// Override hashCode using strategy from Effective Java,</span> <span class="com">// Chapter 11.</span><span class="pln"> @override </span><span class="typ">int</span> <span class="kwd">get</span><span class="pln"> hashCode </span><span class="pun">{</span> <span class="typ">int</span><span class="pln"> result </span><span class="pun">=</span> <span class="lit">17</span><span class="pun">;</span><span class="pln"> result </span><span class="pun">=</span> <span class="lit">37</span> <span class="pun">*</span><span class="pln"> result </span><span class="pun">+</span><span class="pln"> firstName</span><span class="pun">.</span><span class="pln">hashCode</span><span class="pun">;</span><span class="pln"> result </span><span class="pun">=</span> <span class="lit">37</span> <span class="pun">*</span><span class="pln"> result </span><span class="pun">+</span><span class="pln"> lastName</span><span class="pun">.</span><span class="pln">hashCode</span><span class="pun">;</span> <span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span> <span class="pun">}</span> <span class="com">// You should generally implement operator == if you</span> <span class="com">// override hashCode.</span><span class="pln"> @override </span><span class="typ">bool</span> <span class="kwd">operator</span> <span class="pun">==(</span><span class="typ">dynamic</span><span class="pln"> other</span><span class="pun">)</span> <span class="pun">{</span> <span class="kwd">if</span> <span class="pun">(</span><span class="pln">other </span><span class="kwd">is</span><span class="pun">!</span> <span class="typ">Person</span><span class="pun">)</span> <span class="kwd">return</span> <span class="kwd">false</span><span class="pun">;</span> <span class="typ">Person</span><span class="pln"> person </span><span class="pun">=</span><span class="pln"> other</span><span class="pun">;</span> <span class="kwd">return</span> <span class="pun">(</span><span class="pln">person</span><span class="pun">.</span><span class="pln">firstName </span><span class="pun">==</span><span class="pln"> firstName </span><span class="pun">&&</span><span class="pln"> person</span><span class="pun">.</span><span class="pln">lastName </span><span class="pun">==</span><span class="pln"> lastName</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">}</span> <span class="typ">void</span><span class="pln"> main</span><span class="pun">()</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> p1 </span><span class="pun">=</span> <span class="typ">Person</span><span class="pun">(</span><span class="str">'Bob'</span><span class="pun">,</span> <span class="str">'Smith'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> p2 </span><span class="pun">=</span> <span class="typ">Person</span><span class="pun">(</span><span class="str">'Bob'</span><span class="pun">,</span> <span class="str">'Smith'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> p3 </span><span class="pun">=</span> <span class="str">'not a person'</span><span class="pun">;</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">p1</span><span class="pun">.</span><span class="pln">hashCode </span><span class="pun">==</span><span class="pln"> p2</span><span class="pun">.</span><span class="pln">hashCode</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">p1 </span><span class="pun">==</span><span class="pln"> p2</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">p1 </span><span class="pun">!=</span><span class="pln"> p3</span><span class="pun">);</span> <span class="pun">}</span> |
Iteration
The Iterable and Iterator classes support for-in loops. Extend (if possible) or implement Iterable whenever you create a class that can provide Iterators for use in for-in loops. Implement Iterator to define the actual iteration ability.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span class="kwd">class</span> <span class="typ">Process</span> <span class="pun">{</span> <span class="com">// Represents a process...</span> <span class="pun">}</span> <span class="kwd">class</span> <span class="typ">ProcessIterator</span> <span class="kwd">implements</span> <span class="typ">Iterator</span><span class="pun"><</span><span class="typ">Process</span><span class="pun">></span> <span class="pun">{</span><span class="pln"> @override </span><span class="typ">Process</span> <span class="kwd">get</span><span class="pln"> current </span><span class="pun">=></span> <span class="pun">...</span><span class="pln"> @override </span><span class="typ">bool</span><span class="pln"> moveNext</span><span class="pun">()</span> <span class="pun">=></span> <span class="pun">...</span> <span class="pun">}</span> <span class="com">// A mythical class that lets you iterate through all</span> <span class="com">// processes. Extends a subclass of [Iterable].</span> <span class="kwd">class</span> <span class="typ">Processes</span> <span class="kwd">extends</span> <span class="typ">IterableBase</span><span class="pun"><</span><span class="typ">Process</span><span class="pun">></span> <span class="pun">{</span><span class="pln"> @override </span><span class="kwd">final</span> <span class="typ">Iterator</span><span class="pun"><</span><span class="typ">Process</span><span class="pun">></span><span class="pln"> iterator </span><span class="pun">=</span> <span class="typ">ProcessIterator</span><span class="pun">();</span> <span class="pun">}</span> <span class="typ">void</span><span class="pln"> main</span><span class="pun">()</span> <span class="pun">{</span> <span class="com">// Iterable objects can be used with for-in.</span> <span class="kwd">for</span> <span class="pun">(</span><span class="kwd">var</span><span class="pln"> process </span><span class="kwd">in</span> <span class="typ">Processes</span><span class="pun">())</span> <span class="pun">{</span> <span class="com">// Do something with the process.</span> <span class="pun">}</span> <span class="pun">}</span> |
Exceptions
The Dart core library defines many common exceptions and errors. Exceptions are considered conditions that you can plan ahead for and catch. Errors are conditions that you don’t expect or plan for.
A couple of the most common errors are:
- NoSuchMethodError
- Thrown when a receiving object (which might be null) does not implement a method.
- ArgumentError
- Can be thrown by a method that encounters an unexpected argument.
Throwing an application-specific exception is a common way to indicate that an error has occurred. You can define a custom exception by implementing the Exception interface:
1 2 3 4 5 6 7 8 |
<span class="kwd">class</span> <span class="typ">FooException</span> <span class="kwd">implements</span> <span class="typ">Exception</span> <span class="pun">{</span> <span class="kwd">final</span> <span class="typ">String</span><span class="pln"> msg</span><span class="pun">;</span> <span class="kwd">const</span> <span class="typ">FooException</span><span class="pun">([</span><span class="kwd">this</span><span class="pun">.</span><span class="pln">msg</span><span class="pun">]);</span><span class="pln"> @override </span><span class="typ">String</span><span class="pln"> toString</span><span class="pun">()</span> <span class="pun">=></span><span class="pln"> msg </span><span class="pun">??</span> <span class="str">'FooException'</span><span class="pun">;</span> <span class="pun">}</span> |
For more information, see Exceptions (in the language tour) and the Exception API reference.
dart:async – asynchronous programming
Asynchronous programming often uses callback functions, but Dart provides alternatives: Future and Stream objects. A Future is like a promise for a result to be provided sometime in the future. A Stream is a way to get a sequence of values, such as events. Future, Stream, and more are in the dart:async library (API reference).
Note: You don’t always need to use the Future or Stream APIs directly. The Dart language supports asynchronous coding using keywords such as async
and await
. See the asynchronous programming codelab for details.
The dart:async library works in both web apps and command-line apps. To use it, import dart:async:
1 |
<span class="kwd">import</span> <span class="str">'dart:async'</span><span class="pun">;</span> |
Future
Future objects appear throughout the Dart libraries, often as the object returned by an asynchronous method. When a future completes, its value is ready to use.
Using await
Before you directly use the Future API, consider using await
instead. Code that uses await
expressions can be easier to understand than code that uses the Future API.
Consider the following function. It uses Future’s then()
method to execute three asynchronous functions in a row, waiting for each one to complete before executing the next one.
1 2 3 4 5 6 |
<span class="pln">runUsingFuture</span><span class="pun">()</span> <span class="pun">{</span> <span class="com">// ...</span><span class="pln"> findEntryPoint</span><span class="pun">().</span><span class="pln">then</span><span class="pun">((</span><span class="pln">entryPoint</span><span class="pun">)</span> <span class="pun">{</span> <span class="kwd">return</span><span class="pln"> runExecutable</span><span class="pun">(</span><span class="pln">entryPoint</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">);</span> <span class="pun">}).</span><span class="pln">then</span><span class="pun">(</span><span class="pln">flushThenExit</span><span class="pun">);</span> <span class="pun">}</span> |
The equivalent code with await expressions looks more like synchronous code:
1 2 3 4 5 6 |
<span class="pln">runUsingAsyncAwait</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="com">// ...</span> <span class="kwd">var</span><span class="pln"> entryPoint </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> findEntryPoint</span><span class="pun">();</span> <span class="kwd">var</span><span class="pln"> exitCode </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> runExecutable</span><span class="pun">(</span><span class="pln">entryPoint</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">);</span> <span class="kwd">await</span><span class="pln"> flushThenExit</span><span class="pun">(</span><span class="pln">exitCode</span><span class="pun">);</span> <span class="pun">}</span> |
An async
function can catch exceptions from Futures. For example:
1 2 3 4 5 6 7 |
<span class="kwd">var</span><span class="pln"> entryPoint </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> findEntryPoint</span><span class="pun">();</span> <span class="kwd">try</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> exitCode </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> runExecutable</span><span class="pun">(</span><span class="pln">entryPoint</span><span class="pun">,</span><span class="pln"> args</span><span class="pun">);</span> <span class="kwd">await</span><span class="pln"> flushThenExit</span><span class="pun">(</span><span class="pln">exitCode</span><span class="pun">);</span> <span class="pun">}</span> <span class="kwd">catch</span> <span class="pun">(</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span> <span class="com">// Handle the error...</span> <span class="pun">}</span> |
Important: Async functions return Futures. If you don’t want your function to return a future, then use a different solution. For example, you might call an async
function from your function.
For more information on using await
and related Dart language features, see the asynchronous programming codelab.
Basic usage
You can use then()
to schedule code that runs when the future completes. For example, HttpRequest.getString()
returns a Future, since HTTP requests can take a while. Using then()
lets you run some code when that Future has completed and the promised string value is available:
1 2 3 |
<span class="typ">HttpRequest</span><span class="pun">.</span><span class="pln">getString</span><span class="pun">(</span><span class="pln">url</span><span class="pun">).</span><span class="pln">then</span><span class="pun">((</span><span class="typ">String</span><span class="pln"> result</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">result</span><span class="pun">);</span> <span class="pun">});</span> |
Use catchError()
to handle any errors or exceptions that a Future object might throw.
1 2 3 4 5 |
<span class="typ">HttpRequest</span><span class="pun">.</span><span class="pln">getString</span><span class="pun">(</span><span class="pln">url</span><span class="pun">).</span><span class="pln">then</span><span class="pun">((</span><span class="typ">String</span><span class="pln"> result</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">result</span><span class="pun">);</span> <span class="pun">}).</span><span class="pln">catchError</span><span class="pun">((</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span> <span class="com">// Handle or ignore the error.</span> <span class="pun">});</span> |
The then().catchError()
pattern is the asynchronous version of try
–catch
.
Important: Be sure to invoke catchError()
on the result of then()
—not on the result of the original Future. Otherwise, the catchError()
can handle errors only from the original Future’s computation, but not from the handler registered by then()
.
Chaining multiple asynchronous methods
The then()
method returns a Future, providing a useful way to run multiple asynchronous functions in a certain order. If the callback registered with then()
returns a Future, then()
returns an equivalent Future. If the callback returns a value of any other type, then()
creates a new Future that completes with the value.
1 2 3 4 5 6 7 8 |
<span class="typ">Future</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> costlyQuery</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span><span class="pln"> result </span><span class="pun">.</span><span class="pln">then</span><span class="pun">((</span><span class="pln">value</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> expensiveWork</span><span class="pun">(</span><span class="pln">value</span><span class="pun">))</span> <span class="pun">.</span><span class="pln">then</span><span class="pun">((</span><span class="pln">_</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> lengthyComputation</span><span class="pun">())</span> <span class="pun">.</span><span class="pln">then</span><span class="pun">((</span><span class="pln">_</span><span class="pun">)</span> <span class="pun">=></span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Done!'</span><span class="pun">))</span> <span class="pun">.</span><span class="pln">catchError</span><span class="pun">((</span><span class="pln">exception</span><span class="pun">)</span> <span class="pun">{</span> <span class="com">/* Handle exception... */</span> <span class="pun">});</span> |
In the preceding example, the methods run in the following order:
costlyQuery()
expensiveWork()
lengthyComputation()
Here is the same code written using await:
1 2 3 4 5 6 7 8 |
<span class="kwd">try</span> <span class="pun">{</span> <span class="kwd">final</span><span class="pln"> value </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> costlyQuery</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span> <span class="kwd">await</span><span class="pln"> expensiveWork</span><span class="pun">(</span><span class="pln">value</span><span class="pun">);</span> <span class="kwd">await</span><span class="pln"> lengthyComputation</span><span class="pun">();</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Done!'</span><span class="pun">);</span> <span class="pun">}</span> <span class="kwd">catch</span> <span class="pun">(</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span> <span class="com">/* Handle exception... */</span> <span class="pun">}</span> |
Waiting for multiple futures
Sometimes your algorithm needs to invoke many asynchronous functions and wait for them all to complete before continuing. Use the Future.wait()static method to manage multiple Futures and wait for them to complete:
1 2 3 4 5 6 7 8 9 10 |
<span class="typ">Future</span><span class="pln"> deleteLotsOfFiles</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">=></span> <span class="pun">...</span> <span class="typ">Future</span><span class="pln"> copyLotsOfFiles</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">=></span> <span class="pun">...</span> <span class="typ">Future</span><span class="pln"> checksumLotsOfOtherFiles</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">=></span> <span class="pun">...</span> <span class="kwd">await</span> <span class="typ">Future</span><span class="pun">.</span><span class="pln">wait</span><span class="pun">([</span><span class="pln"> deleteLotsOfFiles</span><span class="pun">(),</span><span class="pln"> copyLotsOfFiles</span><span class="pun">(),</span><span class="pln"> checksumLotsOfOtherFiles</span><span class="pun">(),</span> <span class="pun">]);</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Done with all the long steps!'</span><span class="pun">);</span> |
Stream
Stream objects appear throughout Dart APIs, representing sequences of data. For example, HTML events such as button clicks are delivered using streams. You can also read a file as a stream.
Using an asynchronous for loop
Sometimes you can use an asynchronous for loop (await for
) instead of using the Stream API.
Consider the following function. It uses Stream’s listen()
method to subscribe to a list of files, passing in a function literal that searches each file or directory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span class="typ">void</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">List</span><span class="pun"><</span><span class="typ">String</span><span class="pun">></span><span class="pln"> arguments</span><span class="pun">)</span> <span class="pun">{</span> <span class="com">// ...</span> <span class="typ">FileSystemEntity</span><span class="pun">.</span><span class="pln">isDirectory</span><span class="pun">(</span><span class="pln">searchPath</span><span class="pun">).</span><span class="pln">then</span><span class="pun">((</span><span class="pln">isDir</span><span class="pun">)</span> <span class="pun">{</span> <span class="kwd">if</span> <span class="pun">(</span><span class="pln">isDir</span><span class="pun">)</span> <span class="pun">{</span> <span class="kwd">final</span><span class="pln"> startingDir </span><span class="pun">=</span> <span class="typ">Directory</span><span class="pun">(</span><span class="pln">searchPath</span><span class="pun">);</span><span class="pln"> startingDir </span><span class="pun">.</span><span class="pln">list</span><span class="pun">(</span><span class="pln"> recursive</span><span class="pun">:</span><span class="pln"> argResults</span><span class="pun">[</span><span class="pln">recursive</span><span class="pun">],</span><span class="pln"> followLinks</span><span class="pun">:</span><span class="pln"> argResults</span><span class="pun">[</span><span class="pln">followLinks</span><span class="pun">])</span> <span class="pun">.</span><span class="highlight"><span class="pln">listen</span></span><span class="pun">((</span><span class="pln">entity</span><span class="pun">)</span> <span class="pun">{</span> <span class="kwd">if</span> <span class="pun">(</span><span class="pln">entity </span><span class="kwd">is</span> <span class="typ">File</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> searchFile</span><span class="pun">(</span><span class="pln">entity</span><span class="pun">,</span><span class="pln"> searchTerms</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">});</span> <span class="pun">}</span> <span class="kwd">else</span> <span class="pun">{</span><span class="pln"> searchFile</span><span class="pun">(</span><span class="typ">File</span><span class="pun">(</span><span class="pln">searchPath</span><span class="pun">),</span><span class="pln"> searchTerms</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">});</span> <span class="pun">}</span> |
The equivalent code with await expressions, including an asynchronous for loop (await for
), looks more like synchronous code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span class="typ">Future</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">List</span><span class="pun"><</span><span class="typ">String</span><span class="pun">></span><span class="pln"> arguments</span><span class="pun">)</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="com">// ...</span> <span class="kwd">if</span> <span class="pun">(</span><span class="kwd">await</span> <span class="typ">FileSystemEntity</span><span class="pun">.</span><span class="pln">isDirectory</span><span class="pun">(</span><span class="pln">searchPath</span><span class="pun">))</span> <span class="pun">{</span> <span class="kwd">final</span><span class="pln"> startingDir </span><span class="pun">=</span> <span class="typ">Directory</span><span class="pun">(</span><span class="pln">searchPath</span><span class="pun">);</span> <span class="highlight"><span class="kwd">await</span> <span class="kwd">for</span></span> <span class="pun">(</span><span class="kwd">var</span><span class="pln"> entity </span><span class="kwd">in</span><span class="pln"> startingDir</span><span class="pun">.</span><span class="pln">list</span><span class="pun">(</span><span class="pln"> recursive</span><span class="pun">:</span><span class="pln"> argResults</span><span class="pun">[</span><span class="pln">recursive</span><span class="pun">],</span><span class="pln"> followLinks</span><span class="pun">:</span><span class="pln"> argResults</span><span class="pun">[</span><span class="pln">followLinks</span><span class="pun">]))</span> <span class="pun">{</span> <span class="kwd">if</span> <span class="pun">(</span><span class="pln">entity </span><span class="kwd">is</span> <span class="typ">File</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> searchFile</span><span class="pun">(</span><span class="pln">entity</span><span class="pun">,</span><span class="pln"> searchTerms</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">}</span> <span class="pun">}</span> <span class="kwd">else</span> <span class="pun">{</span><span class="pln"> searchFile</span><span class="pun">(</span><span class="typ">File</span><span class="pun">(</span><span class="pln">searchPath</span><span class="pun">),</span><span class="pln"> searchTerms</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">}</span> |
Important: Before using await for
, make sure that it makes the code clearer and that you really do want to wait for all of the stream’s results. For example, you usually should not use await for
for DOM event listeners, because the DOM sends endless streams of events. If you use await for
to register two DOM event listeners in a row, then the second kind of event is never handled.
For more information on using await
and related Dart language features, see the asynchronous programming codelab.
Listening for stream data
To get each value as it arrives, either use await for
or subscribe to the stream using the listen()
method:
1 2 3 4 5 |
<span class="com">// Find a button by ID and add an event handler.</span><span class="pln"> querySelector</span><span class="pun">(</span><span class="str">'#submitInfo'</span><span class="pun">).</span><span class="pln">onClick</span><span class="pun">.</span><span class="pln">listen</span><span class="pun">((</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span> <span class="com">// When the button is clicked, it runs this code.</span><span class="pln"> submitData</span><span class="pun">();</span> <span class="pun">});</span> |
In this example, the onClick
property is a Stream object provided by the “submitInfo” button.
If you care about only one event, you can get it using a property such as first
, last
, or single
. To test the event before handling it, use a method such as firstWhere()
, lastWhere()
, or singleWhere()
.
If you care about a subset of events, you can use methods such as skip()
, skipWhile()
, take()
, takeWhile()
, and where()
.
Transforming stream data
Often, you need to change the format of a stream’s data before you can use it. Use the transform()
method to produce a stream with a different type of data:
1 2 3 |
<span class="kwd">var</span><span class="pln"> lines </span><span class="pun">=</span><span class="pln"> inputStream </span><span class="pun">.</span><span class="pln">transform</span><span class="pun">(</span><span class="pln">utf8</span><span class="pun">.</span><span class="pln">decoder</span><span class="pun">)</span> <span class="pun">.</span><span class="pln">transform</span><span class="pun">(</span><span class="typ">LineSplitter</span><span class="pun">());</span> |
This example uses two transformers. First it uses utf8.decoder to transform the stream of integers into a stream of strings. Then it uses a LineSplitter to transform the stream of strings into a stream of separate lines. These transformers are from the dart:convert library (see the dart:convert section).
Handling errors and completion
How you specify error and completion handling code depends on whether you use an asynchronous for loop (await for
) or the Stream API.
If you use an asynchronous for loop, then use try-catch to handle errors. Code that executes after the stream is closed goes after the asynchronous for loop.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="typ">Future</span><span class="pln"> readFileAwaitFor</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> config </span><span class="pun">=</span> <span class="typ">File</span><span class="pun">(</span><span class="str">'config.txt'</span><span class="pun">);</span> <span class="typ">Stream</span><span class="pun"><</span><span class="typ">List</span><span class="pun"><</span><span class="typ">int</span><span class="pun">>></span><span class="pln"> inputStream </span><span class="pun">=</span><span class="pln"> config</span><span class="pun">.</span><span class="pln">openRead</span><span class="pun">();</span> <span class="kwd">var</span><span class="pln"> lines </span><span class="pun">=</span><span class="pln"> inputStream </span><span class="pun">.</span><span class="pln">transform</span><span class="pun">(</span><span class="pln">utf8</span><span class="pun">.</span><span class="pln">decoder</span><span class="pun">)</span> <span class="pun">.</span><span class="pln">transform</span><span class="pun">(</span><span class="typ">LineSplitter</span><span class="pun">());</span> <span class="highlight"><span class="kwd">try</span></span> <span class="pun">{</span> <span class="kwd">await</span> <span class="kwd">for</span> <span class="pun">(</span><span class="kwd">var</span><span class="pln"> line </span><span class="kwd">in</span><span class="pln"> lines</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Got ${line.length} characters from stream'</span><span class="pun">);</span> <span class="pun">}</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'file is now closed'</span><span class="pun">);</span> <span class="pun">}</span> <span class="highlight"><span class="kwd">catch</span></span> <span class="pun">(</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">}</span> |
If you use the Stream API, then handle errors by registering an onError
listener. Run code after the stream is closed by registering an onDone
listener.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="kwd">var</span><span class="pln"> config </span><span class="pun">=</span> <span class="typ">File</span><span class="pun">(</span><span class="str">'config.txt'</span><span class="pun">);</span> <span class="typ">Stream</span><span class="pun"><</span><span class="typ">List</span><span class="pun"><</span><span class="typ">int</span><span class="pun">>></span><span class="pln"> inputStream </span><span class="pun">=</span><span class="pln"> config</span><span class="pun">.</span><span class="pln">openRead</span><span class="pun">();</span><span class="pln"> inputStream </span><span class="pun">.</span><span class="pln">transform</span><span class="pun">(</span><span class="pln">utf8</span><span class="pun">.</span><span class="pln">decoder</span><span class="pun">)</span> <span class="pun">.</span><span class="pln">transform</span><span class="pun">(</span><span class="typ">LineSplitter</span><span class="pun">())</span> <span class="pun">.</span><span class="pln">listen</span><span class="pun">((</span><span class="typ">String</span><span class="pln"> line</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Got ${line.length} characters from stream'</span><span class="pun">);</span> <span class="pun">},</span> <span class="highlight"><span class="pln">onDone</span></span><span class="pun">:</span> <span class="pun">()</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'file is now closed'</span><span class="pun">);</span> <span class="pun">},</span> <span class="highlight"><span class="pln">onError</span></span><span class="pun">:</span> <span class="pun">(</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span> <span class="pun">});</span> |
More information
For some examples of using Future and Stream in command-line apps, see the dart:io tour. Also see these articles, codelabs, and tutorials:
- Asynchronous programming: futures, async, await
- Futures and error handling
- Asynchronous programming: streams
- Creating streams in Dart
- Dart asynchronous programming: Isolates and event loops
dart:math – math and random
The dart:math library (API reference) provides common functionality such as sine and cosine, maximum and minimum, and constants such as piand e. Most of the functionality in the Math library is implemented as top-level functions.
To use this library in your app, import dart:math.
1 |
<span class="kwd">import</span> <span class="str">'dart:math'</span><span class="pun">;</span> |
Trigonometry
The Math library provides basic trigonometric functions:
1 2 3 4 5 6 7 8 9 10 |
<span class="com">// Cosine</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">cos</span><span class="pun">(</span><span class="pln">pi</span><span class="pun">)</span> <span class="pun">==</span> <span class="pun">-</span><span class="lit">1.0</span><span class="pun">);</span> <span class="com">// Sine</span> <span class="kwd">var</span><span class="pln"> degrees </span><span class="pun">=</span> <span class="lit">30</span><span class="pun">;</span> <span class="kwd">var</span><span class="pln"> radians </span><span class="pun">=</span><span class="pln"> degrees </span><span class="pun">*</span> <span class="pun">(</span><span class="pln">pi </span><span class="pun">/</span> <span class="lit">180</span><span class="pun">);</span> <span class="com">// radians is now 0.52359.</span> <span class="kwd">var</span><span class="pln"> sinOf30degrees </span><span class="pun">=</span><span class="pln"> sin</span><span class="pun">(</span><span class="pln">radians</span><span class="pun">);</span> <span class="com">// sin 30° = 0.5</span> <span class="kwd">assert</span><span class="pun">((</span><span class="pln">sinOf30degrees </span><span class="pun">-</span> <span class="lit">0.5</span><span class="pun">).</span><span class="pln">abs</span><span class="pun">()</span> <span class="pun"><</span> <span class="lit">0.01</span><span class="pun">);</span> |
Note: These functions use radians, not degrees!
Maximum and minimum
The Math library provides max()
and min()
methods:
1 2 |
<span class="kwd">assert</span><span class="pun">(</span><span class="pln">max</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span> <span class="lit">1000</span><span class="pun">)</span> <span class="pun">==</span> <span class="lit">1000</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">min</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span> <span class="pun">-</span><span class="lit">1000</span><span class="pun">)</span> <span class="pun">==</span> <span class="pun">-</span><span class="lit">1000</span><span class="pun">);</span> |
Math constants
Find your favorite constants—pi, e, and more—in the Math library:
1 2 3 4 |
<span class="com">// See the Math library for additional constants.</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span> <span class="com">// 2.718281828459045</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">pi</span><span class="pun">);</span> <span class="com">// 3.141592653589793</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">sqrt2</span><span class="pun">);</span> <span class="com">// 1.4142135623730951</span> |
Random numbers
Generate random numbers with the Random class. You can optionally provide a seed to the Random constructor.
1 2 3 |
<span class="kwd">var</span><span class="pln"> random </span><span class="pun">=</span> <span class="typ">Random</span><span class="pun">();</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">nextDouble</span><span class="pun">();</span> <span class="com">// Between 0.0 and 1.0: [0, 1)</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">nextInt</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span> <span class="com">// Between 0 and 9.</span> |
You can even generate random booleans:
1 2 |
<span class="kwd">var</span><span class="pln"> random </span><span class="pun">=</span> <span class="typ">Random</span><span class="pun">();</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">nextBool</span><span class="pun">();</span> <span class="com">// true or false</span> |
More information
Refer to the Math API reference for a full list of methods. Also see the API reference for num, int, and double.
dart:convert – decoding and encoding JSON, UTF-8, and more
The dart:convert library (API reference) has converters for JSON and UTF-8, as well as support for creating additional converters. JSON is a simple text format for representing structured objects and collections. UTF-8 is a common variable-width encoding that can represent every character in the Unicode character set.
The dart:convert library works in both web apps and command-line apps. To use it, import dart:convert.
1 |
<span class="kwd">import</span> <span class="str">'dart:convert'</span><span class="pun">;</span> |
Decoding and encoding JSON
Decode a JSON-encoded string into a Dart object with jsonDecode()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="com">// NOTE: Be sure to use double quotes ("),</span> <span class="com">// not single quotes ('), inside the JSON string.</span> <span class="com">// This string is JSON, not Dart.</span> <span class="kwd">var</span><span class="pln"> jsonString </span><span class="pun">=</span> <span class="str">''' [ {"score": 40}, {"score": 80} ] '''</span><span class="pun">;</span> <span class="kwd">var</span><span class="pln"> scores </span><span class="pun">=</span><span class="pln"> jsonDecode</span><span class="pun">(</span><span class="pln">jsonString</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">scores </span><span class="kwd">is</span> <span class="typ">List</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> firstScore </span><span class="pun">=</span><span class="pln"> scores</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">firstScore </span><span class="kwd">is</span> <span class="typ">Map</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">firstScore</span><span class="pun">[</span><span class="str">'score'</span><span class="pun">]</span> <span class="pun">==</span> <span class="lit">40</span><span class="pun">);</span> |
Encode a supported Dart object into a JSON-formatted string with jsonEncode()
:
1 2 3 4 5 6 7 8 9 10 11 |
<span class="kwd">var</span><span class="pln"> scores </span><span class="pun">=</span> <span class="pun">[</span> <span class="pun">{</span><span class="str">'score'</span><span class="pun">:</span> <span class="lit">40</span><span class="pun">},</span> <span class="pun">{</span><span class="str">'score'</span><span class="pun">:</span> <span class="lit">80</span><span class="pun">},</span> <span class="pun">{</span><span class="str">'score'</span><span class="pun">:</span> <span class="lit">100</span><span class="pun">,</span> <span class="str">'overtime'</span><span class="pun">:</span> <span class="kwd">true</span><span class="pun">,</span> <span class="str">'special_guest'</span><span class="pun">:</span> <span class="kwd">null</span><span class="pun">}</span> <span class="pun">];</span> <span class="kwd">var</span><span class="pln"> jsonText </span><span class="pun">=</span><span class="pln"> jsonEncode</span><span class="pun">(</span><span class="pln">scores</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">jsonText </span><span class="pun">==</span> <span class="str">'[{"score":40},{"score":80},'</span> <span class="str">'{"score":100,"overtime":true,'</span> <span class="str">'"special_guest":null}]'</span><span class="pun">);</span> |
Only objects of type int, double, String, bool, null, List, or Map (with string keys) are directly encodable into JSON. List and Map objects are encoded recursively.
You have two options for encoding objects that aren’t directly encodable. The first is to invoke encode()
with a second argument: a function that returns an object that is directly encodable. Your second option is to omit the second argument, in which case the encoder calls the object’s toJson()
method.
For more examples and links to JSON-related packages, see Using JSON.
Decoding and encoding UTF-8 characters
Use utf8.decode()
to decode UTF8-encoded bytes to a Dart string:
1 2 3 4 5 6 7 8 9 10 11 |
<span class="typ">List</span><span class="pun"><</span><span class="typ">int</span><span class="pun">></span><span class="pln"> utf8Bytes </span><span class="pun">=</span> <span class="pun">[</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0x8e</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xb1</span><span class="pun">,</span> <span class="lit">0xc5</span><span class="pun">,</span> <span class="lit">0xa3</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xa9</span><span class="pun">,</span> <span class="lit">0x72</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xb1</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xa5</span><span class="pun">,</span> <span class="lit">0xc5</span><span class="pun">,</span> <span class="lit">0xa3</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xae</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xb6</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xb1</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xa5</span><span class="pun">,</span> <span class="lit">0xc4</span><span class="pun">,</span> <span class="lit">0xbc</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xae</span><span class="pun">,</span> <span class="lit">0xc5</span><span class="pun">,</span> <span class="lit">0xbe</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xa5</span><span class="pun">,</span> <span class="lit">0xc5</span><span class="pun">,</span> <span class="lit">0xa3</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xae</span><span class="pun">,</span> <span class="lit">0xe1</span><span class="pun">,</span> <span class="lit">0xbb</span><span class="pun">,</span> <span class="lit">0x9d</span><span class="pun">,</span> <span class="lit">0xc3</span><span class="pun">,</span> <span class="lit">0xb1</span> <span class="pun">];</span> <span class="kwd">var</span><span class="pln"> funnyWord </span><span class="pun">=</span><span class="pln"> utf8</span><span class="pun">.</span><span class="pln">decode</span><span class="pun">(</span><span class="pln">utf8Bytes</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">funnyWord </span><span class="pun">==</span> <span class="str">'Îñţérñåţîöñåļîžåţîờñ'</span><span class="pun">);</span> |
To convert a stream of UTF-8 characters into a Dart string, specify utf8.decoder
to the Stream transform()
method:
1 2 3 4 5 6 7 8 9 10 |
<span class="kwd">var</span><span class="pln"> lines </span><span class="pun">=</span> <span class="highlight"><span class="pln">utf8</span><span class="pun">.</span><span class="pln">decoder</span></span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="pln">inputStream</span><span class="pun">).</span><span class="pln">transform</span><span class="pun">(</span><span class="typ">LineSplitter</span><span class="pun">());</span> <span class="kwd">try</span> <span class="pun">{</span> <span class="kwd">await</span> <span class="kwd">for</span> <span class="pun">(</span><span class="kwd">var</span><span class="pln"> line </span><span class="kwd">in</span><span class="pln"> lines</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Got ${line.length} characters from stream'</span><span class="pun">);</span> <span class="pun">}</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'file is now closed'</span><span class="pun">);</span> <span class="pun">}</span> <span class="kwd">catch</span> <span class="pun">(</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span> <span class="pun">}</span> |
Use utf8.encode()
to encode a Dart string as a list of UTF8-encoded bytes:
1 2 3 4 5 6 |
<span class="typ">List</span><span class="pun"><</span><span class="typ">int</span><span class="pun">></span><span class="pln"> encoded </span><span class="pun">=</span><span class="pln"> utf8</span><span class="pun">.</span><span class="pln">encode</span><span class="pun">(</span><span class="str">'Îñţérñåţîöñåļîžåţîờñ'</span><span class="pun">);</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">encoded</span><span class="pun">.</span><span class="pln">length </span><span class="pun">==</span><span class="pln"> utf8Bytes</span><span class="pun">.</span><span class="pln">length</span><span class="pun">);</span> <span class="kwd">for</span> <span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span> <span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><</span><span class="pln"> encoded</span><span class="pun">.</span><span class="pln">length</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span> <span class="pun">{</span> <span class="kwd">assert</span><span class="pun">(</span><span class="pln">encoded</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span> <span class="pun">==</span><span class="pln"> utf8Bytes</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]);</span> <span class="pun">}</span> |
Other functionality
The dart:convert library also has converters for ASCII and ISO-8859-1 (Latin1). For details, see the API reference for the dart:convert library.
dart:html – browser-based apps
Use the dart:html library to program the browser, manipulate objects and elements in the DOM, and access HTML5 APIs. DOM stands for Document Object Model, which describes the hierarchy of an HTML page.
Other common uses of dart:html are manipulating styles (CSS), getting data using HTTP requests, and exchanging data using WebSockets. HTML5 (and dart:html) has many additional APIs that this section doesn’t cover. Only web apps can use dart:html, not command-line apps.
Note: For a higher level approach to web app UIs, use a web framework such as AngularDart.
To use the HTML library in your web app, import dart:html:
1 2 |
<span class="kn">import</span> <span class="s">'dart:html'</span><span class="o">;</span> |
Manipulating the DOM
To use the DOM, you need to know about windows, documents, elements, and nodes.
A Window object represents the actual window of the web browser. Each Window has a Document object, which points to the document that’s currently loaded. The Window object also has accessors to various APIs such as IndexedDB (for storing data), requestAnimationFrame (for animations), and more. In tabbed browsers, each tab has its own Window object.
With the Document object, you can create and manipulate Element objects within the document. Note that the document itself is an element and can be manipulated.
The DOM models a tree of Nodes. These nodes are often elements, but they can also be attributes, text, comments, and other DOM types. Except for the root node, which has no parent, each node in the DOM has one parent and might have many children.
Finding elements
To manipulate an element, you first need an object that represents it. You can get this object using a query.
Find one or more elements using the top-level functions querySelector()
and querySelectorAll()
. You can query by ID, class, tag, name, or any combination of these. The CSS Selector Specification guide defines the formats of the selectors such as using a # prefix to specify IDs and a period (.) for classes.
The querySelector()
function returns the first element that matches the selector, while querySelectorAll()
returns a collection of elements that match the selector.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span class="c1">// Find an element by id (an-id).</span> <span class="n">Element</span> <span class="n">elem1</span> <span class="o">=</span> <span class="n">querySelector</span><span class="o">(</span><span class="s">'#an-id'</span><span class="o">);</span> <span class="c1">// Find an element by class (a-class).</span> <span class="n">Element</span> <span class="n">elem2</span> <span class="o">=</span> <span class="n">querySelector</span><span class="o">(</span><span class="s">'.a-class'</span><span class="o">);</span> <span class="c1">// Find all elements by tag (<div>).</span> <span class="n">List</span><span class="o"><</span><span class="n">Element</span><span class="o">></span> <span class="n">elems1</span> <span class="o">=</span> <span class="n">querySelectorAll</span><span class="o">(</span><span class="s">'div'</span><span class="o">);</span> <span class="c1">// Find all text inputs.</span> <span class="n">List</span><span class="o"><</span><span class="n">Element</span><span class="o">></span> <span class="n">elems2</span> <span class="o">=</span> <span class="n">querySelectorAll</span><span class="o">(</span> <span class="s">'input[type="text"]'</span><span class="o">,</span> <span class="o">);</span> <span class="c1">// Find all elements with the CSS class 'class'</span> <span class="c1">// inside of a <p> that is inside an element with</span> <span class="c1">// the ID 'id'.</span> <span class="n">List</span><span class="o"><</span><span class="n">Element</span><span class="o">></span> <span class="n">elems3</span> <span class="o">=</span> <span class="n">querySelectorAll</span><span class="o">(</span><span class="s">'#id p.class'</span><span class="o">);</span> |
Manipulating elements
You can use properties to change the state of an element. Node and its subtype Element define the properties that all elements have. For example, all elements have classes
, hidden
, id
, style
, and title
properties that you can use to set state. Subclasses of Element define additional properties, such as the href
property of AnchorElement.
Consider this example of specifying an anchor element in HTML:
1 2 |
<span class="nt"><a</span> <span class="na">id=</span><span class="s">"example"</span> <span class="na">href=</span><span class="s">"http://example.com"</span><span class="nt">></span>link text<span class="nt"></a></span> |
This <a> tag specifies an element with an href
attribute and a text node (accessible via a text
property) that contains the string “linktext”. To change the URL that the link goes to, you can use AnchorElement’s href
property:
1 2 3 |
<span class="kd">var</span> <span class="n">anchor</span> <span class="o">=</span> <span class="n">querySelector</span><span class="o">(</span><span class="s">'#example'</span><span class="o">)</span> <span class="k">as</span> <span class="n">AnchorElement</span><span class="o">;</span> <span class="n">anchor</span><span class="o">.</span><span class="na">href</span> <span class="o">=</span> <span class="s">'http://dartlang.org'</span><span class="o">;</span> |
Often you need to set properties on multiple elements. For example, the following code sets the hidden
property of all elements that have a class of “mac”, “win”, or “linux”. Setting the hidden
property to true has the same effect as adding display:none
to the CSS.
1 2 3 4 5 6 7 |
<span class="o"><!--</span> <span class="n">In</span> <span class="nl">HTML:</span> <span class="o">--></span> <span class="o"><</span><span class="n">p</span><span class="o">></span> <span class="o"><</span><span class="n">span</span> <span class="kd">class</span><span class="err">="</span><span class="nc">linux</span><span class="s">">Words for Linux</span> <span class="</span><span class="n">macos</span><span class="s">">Words for Mac</span> <span class="</span><span class="n">windows</span><span class="s">">Words for Windows</span> </p> </span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="c1">// In Dart:</span> <span class="kd">final</span> <span class="n">osList</span> <span class="o">=</span> <span class="o">[</span><span class="s">'macos'</span><span class="o">,</span> <span class="s">'windows'</span><span class="o">,</span> <span class="s">'linux'</span><span class="o">];</span> <span class="kd">final</span> <span class="n">userOs</span> <span class="o">=</span> <span class="n">determineUserOs</span><span class="o">();</span> <span class="c1">// For each possible OS...</span> <span class="k">for</span> <span class="o">(</span><span class="kd">var</span> <span class="n">os</span> <span class="k">in</span> <span class="n">osList</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// Matches user OS?</span> <span class="kt">bool</span> <span class="n">shouldShow</span> <span class="o">=</span> <span class="o">(</span><span class="n">os</span> <span class="o">==</span> <span class="n">userOs</span><span class="o">);</span> <span class="c1">// Find all elements with class=os. For example, if</span> <span class="c1">// os == 'windows', call querySelectorAll('.windows')</span> <span class="c1">// to find all elements with the class "windows".</span> <span class="c1">// Note that '.$os' uses string interpolation.</span> <span class="k">for</span> <span class="o">(</span><span class="kd">var</span> <span class="n">elem</span> <span class="k">in</span> <span class="n">querySelectorAll</span><span class="o">(</span><span class="s">'.</span><span class="si">$os</span><span class="s">'</span><span class="o">))</span> <span class="o">{</span> <span class="n">elem</span><span class="o">.</span><span class="na">hidden</span> <span class="o">=</span> <span class="o">!</span><span class="n">shouldShow</span><span class="o">;</span> <span class="c1">// Show or hide.</span> <span class="o">}</span> <span class="o">}</span> |
When the right property isn’t available or convenient, you can use Element’s attributes
property. This property is a Map<String, String>
, where the keys are attribute names. For a list of attribute names and their meanings, see the MDN Attributes page. Here’s an example of setting an attribute’s value:
1 2 |
<span class="n">elem</span><span class="o">.</span><span class="na">attributes</span><span class="o">[</span><span class="s">'someAttribute'</span><span class="o">]</span> <span class="o">=</span> <span class="s">'someValue'</span><span class="o">;</span> |
Creating elements
You can add to existing HTML pages by creating new elements and attaching them to the DOM. Here’s an example of creating a paragraph (<p>) element:
1 2 3 |
<span class="kd">var</span> <span class="n">elem</span> <span class="o">=</span> <span class="n">ParagraphElement</span><span class="o">();</span> <span class="n">elem</span><span class="o">.</span><span class="na">text</span> <span class="o">=</span> <span class="s">'Creating is easy!'</span><span class="o">;</span> |
You can also create an element by parsing HTML text. Any child elements are also parsed and created.
1 2 3 4 |
<span class="kd">var</span> <span class="n">elem2</span> <span class="o">=</span> <span class="n">Element</span><span class="o">.</span><span class="na">html</span><span class="o">(</span> <span class="s">'<p>Creating <em>is</em> easy!</p>'</span><span class="o">,</span> <span class="o">);</span> |
Note that elem2
is a ParagraphElement
in the preceding example.
Attach the newly created element to the document by assigning a parent to the element. You can add an element to any existing element’s children. In the following example, body
is an element, and its child elements are accessible (as a List<Element>) from the children
property.
1 2 |
<span class="n">document</span><span class="o">.</span><span class="na">body</span><span class="o">.</span><span class="na">children</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">elem2</span><span class="o">);</span> |
Adding, replacing, and removing nodes
Recall that elements are just a kind of node. You can find all the children of a node using the nodes
property of Node, which returns a List<Node> (as opposed to children
, which omits non-Element nodes). Once you have this list, you can use the usual List methods and operators to manipulate the children of the node.
To add a node as the last child of its parent, use the List add()
method:
1 2 |
<span class="n">querySelector</span><span class="o">(</span><span class="s">'#inputs'</span><span class="o">).</span><span class="na">nodes</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">elem</span><span class="o">);</span> |
To replace a node, use the Node replaceWith()
method:
1 2 |
<span class="n">querySelector</span><span class="o">(</span><span class="s">'#status'</span><span class="o">).</span><span class="na">replaceWith</span><span class="o">(</span><span class="n">elem</span><span class="o">);</span> |
To remove a node, use the Node remove()
method:
1 2 3 |
<span class="c1">// Find a node by ID, and remove it from the DOM.</span> <span class="n">querySelector</span><span class="o">(</span><span class="s">'#expendable'</span><span class="o">).</span><span class="na">remove</span><span class="o">();</span> |
Manipulating CSS styles
CSS, or cascading style sheets, defines the presentation styles of DOM elements. You can change the appearance of an element by attaching ID and class attributes to it.
Each element has a classes
field, which is a list. Add and remove CSS classes simply by adding and removing strings from this collection. For example, the following sample adds the warning
class to an element:
1 2 3 |
<span class="kd">var</span> <span class="n">elem</span> <span class="o">=</span> <span class="n">querySelector</span><span class="o">(</span><span class="s">'#message'</span><span class="o">);</span> <span class="n">elem</span><span class="o">.</span><span class="na">classes</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="s">'warning'</span><span class="o">);</span> |
It’s often very efficient to find an element by ID. You can dynamically set an element ID with the id
property:
1 2 3 4 |
<span class="kd">var</span> <span class="n">message</span> <span class="o">=</span> <span class="n">DivElement</span><span class="o">();</span> <span class="n">message</span><span class="o">.</span><span class="na">id</span> <span class="o">=</span> <span class="s">'message2'</span><span class="o">;</span> <span class="n">message</span><span class="o">.</span><span class="na">text</span> <span class="o">=</span> <span class="s">'Please subscribe to the Dart mailing list.'</span><span class="o">;</span> |
You can reduce the redundant text in this example by using method cascades:
1 2 3 4 |
<span class="kd">var</span> <span class="n">message</span> <span class="o">=</span> <span class="n">DivElement</span><span class="o">()</span> <span class="o">..</span><span class="na">id</span> <span class="o">=</span> <span class="s">'message2'</span> <span class="o">..</span><span class="na">text</span> <span class="o">=</span> <span class="s">'Please subscribe to the Dart mailing list.'</span><span class="o">;</span> |
While using IDs and classes to associate an element with a set of styles is best practice, sometimes you want to attach a specific style directly to the element:
1 2 3 4 |
<span class="n">message</span><span class="o">.</span><span class="na">style</span> <span class="o">..</span><span class="na">fontWeight</span> <span class="o">=</span> <span class="s">'bold'</span> <span class="o">..</span><span class="na">fontSize</span> <span class="o">=</span> <span class="s">'3em'</span><span class="o">;</span> |
Handling events
To respond to external events such as clicks, changes of focus, and selections, add an event listener. You can add an event listener to any element on the page. Event dispatch and propagation is a complicated subject; research the details if you’re new to web programming.
Add an event handler using element.onEvent.listen(function)
, where Event
is the event name and function
is the event handler.
For example, here’s how you can handle clicks on a button:
1 2 3 4 5 6 |
<span class="c1">// Find a button by ID and add an event handler.</span> <span class="n">querySelector</span><span class="o">(</span><span class="s">'#submitInfo'</span><span class="o">).</span><span class="na">onClick</span><span class="o">.</span><span class="na">listen</span><span class="o">((</span><span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// When the button is clicked, it runs this code.</span> <span class="n">submitData</span><span class="o">();</span> <span class="o">});</span> |
Events can propagate up and down through the DOM tree. To discover which element originally fired the event, use e.target
:
1 2 3 4 5 |
<span class="n">document</span><span class="o">.</span><span class="na">body</span><span class="o">.</span><span class="na">onClick</span><span class="o">.</span><span class="na">listen</span><span class="o">((</span><span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="kd">final</span> <span class="n">clickedElem</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="na">target</span><span class="o">;</span> <span class="c1">// ...</span> <span class="o">});</span> |
To see all the events for which you can register an event listener, look for “onEventType” properties in the API docs for Element and its subclasses. Some common events include:
- change
- blur
- keyDown
- keyUp
- mouseDown
- mouseUp
Using HTTP resources with HttpRequest
Formerly known as XMLHttpRequest, the HttpRequest class gives you access to HTTP resources from within your browser-based app. Traditionally, AJAX-style apps make heavy use of HttpRequest. Use HttpRequest to dynamically load JSON data or any other resource from a web server. You can also dynamically send data to a web server.
Getting data from the server
The HttpRequest static method getString()
is an easy way to get data from a web server. Use await
with the getString()
call to ensure that you have the data before continuing execution.
1 2 3 4 5 |
<span class="n">Future</span> <span class="nf">main</span><span class="p">(</span><span class="o">)</span> <span class="n">async</span> <span class="o">{</span> <span class="kt">String</span> <span class="n">pageHtml</span> <span class="o">=</span> <span class="o">[!</span><span class="n">await</span> <span class="n">HttpRequest</span><span class="o">.</span><span class="na">getString</span><span class="o">(</span><span class="n">url</span><span class="o">);!]</span> <span class="c1">// Do something with pageHtml...</span> <span class="o">}</span> |
Use try-catch to specify an error handler:
1 2 3 4 5 6 7 |
<span class="k">try</span> <span class="o">{</span> <span class="kd">var</span> <span class="n">data</span> <span class="o">=</span> <span class="n">await</span> <span class="n">HttpRequest</span><span class="o">.</span><span class="na">getString</span><span class="o">(</span><span class="n">jsonUri</span><span class="o">);</span> <span class="c1">// Process data...</span> <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// Handle exception...</span> <span class="o">}</span> |
If you need access to the HttpRequest, not just the text data it retrieves, you can use the request()
static method instead of getString()
. Here’s an example of reading XML data:
1 2 3 4 5 6 7 8 9 10 11 |
<span class="n">Future</span> <span class="nf">main</span><span class="p">(</span><span class="o">)</span> <span class="n">async</span> <span class="o">{</span> <span class="n">HttpRequest</span> <span class="n">req</span> <span class="o">=</span> <span class="n">await</span> <span class="n">HttpRequest</span><span class="o">.</span><span class="na">request</span><span class="o">(</span> <span class="n">url</span><span class="o">,</span> <span class="nl">method:</span> <span class="s">'HEAD'</span><span class="o">,</span> <span class="o">);</span> <span class="k">if</span> <span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">status</span> <span class="o">==</span> <span class="mi">200</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// Successful URL access...</span> <span class="o">}</span> <span class="c1">// ···</span> <span class="o">}</span> |
You can also use the full API to handle more interesting cases. For example, you can set arbitrary headers.
The general flow for using the full API of HttpRequest is as follows:
- Create the HttpRequest object.
- Open the URL with either
GET
orPOST
. - Attach event handlers.
- Send the request.
For example:
1 2 3 4 5 6 |
<span class="kd">var</span> <span class="n">request</span> <span class="o">=</span> <span class="n">HttpRequest</span><span class="o">();</span> <span class="n">request</span> <span class="o">..</span><span class="na">open</span><span class="o">(</span><span class="s">'POST'</span><span class="o">,</span> <span class="n">url</span><span class="o">)</span> <span class="o">..</span><span class="na">onLoadEnd</span><span class="o">.</span><span class="na">listen</span><span class="o">((</span><span class="n">e</span><span class="o">)</span> <span class="o">=></span> <span class="n">requestComplete</span><span class="o">(</span><span class="n">request</span><span class="o">))</span> <span class="o">..</span><span class="na">send</span><span class="o">(</span><span class="n">encodedData</span><span class="o">);</span> |
Sending data to the server
HttpRequest can send data to the server using the HTTP method POST. For example, you might want to dynamically submit data to a form handler. Sending JSON data to a RESTful web service is another common example.
Submitting data to a form handler requires you to provide name-value pairs as URI-encoded strings. (Information about the URI class is in the URIs section of the Dart Library Tour.) You must also set the Content-type
header to application/x-www-form-urlencode
if you wish to send data to a form handler.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span class="kt">String</span> <span class="nf">encodeMap</span><span class="p">(</span><span class="n">Map</span> <span class="n">data</span><span class="o">)</span> <span class="o">=></span> <span class="n">data</span><span class="o">.</span><span class="na">keys</span> <span class="o">.</span><span class="na">map</span><span class="o">((</span><span class="n">k</span><span class="o">)</span> <span class="o">=></span> <span class="s">'</span><span class="si">${Uri.encodeComponent(k)}</span><span class="s">=</span><span class="si">${Uri.encodeComponent(data[k])}</span><span class="s">'</span><span class="o">)</span> <span class="o">.</span><span class="na">join</span><span class="o">(</span><span class="s">'&'</span><span class="o">);</span> <span class="n">Future</span> <span class="n">main</span><span class="o">()</span> <span class="n">async</span> <span class="o">{</span> <span class="kd">var</span> <span class="n">data</span> <span class="o">=</span> <span class="o">{</span><span class="s">'dart'</span><span class="o">:</span> <span class="s">'fun'</span><span class="o">,</span> <span class="s">'angular'</span><span class="o">:</span> <span class="s">'productive'</span><span class="o">};</span> <span class="kd">var</span> <span class="n">request</span> <span class="o">=</span> <span class="n">HttpRequest</span><span class="o">();</span> <span class="n">request</span> <span class="o">..</span><span class="na">open</span><span class="o">(</span><span class="s">'POST'</span><span class="o">,</span> <span class="n">url</span><span class="o">)</span> <span class="o">..</span><span class="na">setRequestHeader</span><span class="o">(</span> <span class="s">'Content-type'</span><span class="o">,</span> <span class="s">'application/x-www-form-urlencoded'</span><span class="o">,</span> <span class="o">)</span> <span class="o">..</span><span class="na">send</span><span class="o">(</span><span class="n">encodeMap</span><span class="o">(</span><span class="n">data</span><span class="o">));</span> <span class="n">await</span> <span class="n">request</span><span class="o">.</span><span class="na">onLoadEnd</span><span class="o">.</span><span class="na">first</span><span class="o">;</span> <span class="k">if</span> <span class="o">(</span><span class="n">request</span><span class="o">.</span><span class="na">status</span> <span class="o">==</span> <span class="mi">200</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// Successful URL access...</span> <span class="o">}</span> <span class="c1">// ···</span> <span class="o">}</span> |
Sending and receiving real-time data with WebSockets
A WebSocket allows your web app to exchange data with a server interactively—no polling necessary. A server creates the WebSocket and listens for requests on a URL that starts with ws://—for example, ws://127.0.0.1:1337/ws. The data transmitted over a WebSocket can be a string or a blob. Often, the data is a JSON-formatted string.
To use a WebSocket in your web app, first create a WebSocket object, passing the WebSocket URL as an argument:
1 2 |
<span class="kd">var</span> <span class="n">ws</span> <span class="o">=</span> <span class="n">WebSocket</span><span class="o">(</span><span class="s">'ws://echo.websocket.org'</span><span class="o">);</span> |
Sending data
To send string data on the WebSocket, use the send()
method:
1 2 |
<span class="n">ws</span><span class="o">.</span><span class="na">send</span><span class="o">(</span><span class="s">'Hello from Dart!'</span><span class="o">);</span> |
Receiving data
To receive data on the WebSocket, register a listener for message events:
1 2 3 4 |
<span class="n">ws</span><span class="o">.</span><span class="na">onMessage</span><span class="o">.</span><span class="na">listen</span><span class="o">((</span><span class="n">MessageEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="n">print</span><span class="o">(</span><span class="s">'Received message: </span><span class="si">${e.data}</span><span class="s">'</span><span class="o">);</span> <span class="o">});</span> |
The message event handler receives a MessageEvent object. This object’s data
field has the data from the server.
Handling WebSocket events
Your app can handle the following WebSocket events: open, close, error, and (as shown earlier) message. Here’s an example of a method that creates a WebSocket object and registers handlers for open, close, error, and message events:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<span class="kt">void</span> <span class="nf">initWebSocket</span><span class="p">(</span><span class="o">[</span><span class="kt">int</span> <span class="n">retrySeconds</span> <span class="o">=</span> <span class="mi">1</span><span class="o">])</span> <span class="o">{</span> <span class="kd">var</span> <span class="n">reconnectScheduled</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span> <span class="n">print</span><span class="o">(</span><span class="s">"Connecting to websocket"</span><span class="o">);</span> <span class="kt">void</span> <span class="n">scheduleReconnect</span><span class="o">()</span> <span class="o">{</span> <span class="k">if</span> <span class="o">(!</span><span class="n">reconnectScheduled</span><span class="o">)</span> <span class="o">{</span> <span class="n">Timer</span><span class="o">(</span><span class="n">Duration</span><span class="o">(</span><span class="nl">seconds:</span> <span class="n">retrySeconds</span><span class="o">),</span> <span class="o">()</span> <span class="o">=></span> <span class="n">initWebSocket</span><span class="o">(</span><span class="n">retrySeconds</span> <span class="o">*</span> <span class="mi">2</span><span class="o">));</span> <span class="o">}</span> <span class="n">reconnectScheduled</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span> <span class="o">}</span> <span class="n">ws</span><span class="o">.</span><span class="na">onOpen</span><span class="o">.</span><span class="na">listen</span><span class="o">((</span><span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="n">print</span><span class="o">(</span><span class="s">'Connected'</span><span class="o">);</span> <span class="n">ws</span><span class="o">.</span><span class="na">send</span><span class="o">(</span><span class="s">'Hello from Dart!'</span><span class="o">);</span> <span class="o">});</span> <span class="n">ws</span><span class="o">.</span><span class="na">onClose</span><span class="o">.</span><span class="na">listen</span><span class="o">((</span><span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="n">print</span><span class="o">(</span><span class="s">'Websocket closed, retrying in '</span> <span class="o">+</span> <span class="s">'</span><span class="si">$retrySeconds</span><span class="s"> seconds'</span><span class="o">);</span> <span class="n">scheduleReconnect</span><span class="o">();</span> <span class="o">});</span> <span class="n">ws</span><span class="o">.</span><span class="na">onError</span><span class="o">.</span><span class="na">listen</span><span class="o">((</span><span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="n">print</span><span class="o">(</span><span class="s">"Error connecting to ws"</span><span class="o">);</span> <span class="n">scheduleReconnect</span><span class="o">();</span> <span class="o">});</span> <span class="n">ws</span><span class="o">.</span><span class="na">onMessage</span><span class="o">.</span><span class="na">listen</span><span class="o">((</span><span class="n">MessageEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="n">print</span><span class="o">(</span><span class="s">'Received message: </span><span class="si">${e.data}</span><span class="s">'</span><span class="o">);</span> <span class="o">});</span> <span class="o">}</span> |
More information
This section barely scratched the surface of using the dart:html library. For more information, see the documentation for dart:html. Dart has additional libraries for more specialized web APIs, such as web audio, IndexedDB, and WebGL.
For more information about Dart web libraries, see the web library overview.
dart:io – I/O for servers and command-line apps
The dart:io library provides APIs to deal with files, directories, processes, sockets, WebSockets, and HTTP clients and servers.
Important: Only Flutter mobile apps, command-line scripts, and servers can import and use dart:io
, not web apps.
In general, the dart:io library implements and promotes an asynchronous API. Synchronous methods can easily block an application, making it difficult to scale. Therefore, most operations return results via Future or Stream objects, a pattern common with modern server platforms such as Node.js.
The few synchronous methods in the dart:io library are clearly marked with a Sync suffix on the method name. Synchronous methods aren’t covered here.
To use the dart:io library you must import it:
1 |
<span class="kwd">import</span> <span class="str">'dart:io'</span><span class="pun">;</span> |
Files and directories
The I/O library enables command-line apps to read and write files and browse directories. You have two choices for reading the contents of a file: all at once, or streaming. Reading a file all at once requires enough memory to store all the contents of the file. If the file is very large or you want to process it while reading it, you should use a Stream, as described in Streaming file contents.
Reading a file as text
When reading a text file encoded using UTF-8, you can read the entire file contents with readAsString()
. When the individual lines are important, you can use readAsLines()
. In both cases, a Future object is returned that provides the contents of the file as one or more strings.
1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="typ">Future</span><span class="pln"> main</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> config </span><span class="pun">=</span> <span class="typ">File</span><span class="pun">(</span><span class="str">'config.txt'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> contents</span><span class="pun">;</span> <span class="com">// Put the whole file in a single string.</span><span class="pln"> contents </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> config</span><span class="pun">.</span><span class="pln">readAsString</span><span class="pun">();</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'The file is ${contents.length} characters long.'</span><span class="pun">);</span> <span class="com">// Put each line of the file into its own string.</span><span class="pln"> contents </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> config</span><span class="pun">.</span><span class="pln">readAsLines</span><span class="pun">();</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'The file is ${contents.length} lines long.'</span><span class="pun">);</span> <span class="pun">}</span> |
Reading a file as binary
The following code reads an entire file as bytes into a list of ints. The call to readAsBytes()
returns a Future, which provides the result when it’s available.
1 2 3 4 5 6 |
<span class="typ">Future</span><span class="pln"> main</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> config </span><span class="pun">=</span> <span class="typ">File</span><span class="pun">(</span><span class="str">'config.txt'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> contents </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> config</span><span class="pun">.</span><span class="pln">readAsBytes</span><span class="pun">();</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'The file is ${contents.length} bytes long.'</span><span class="pun">);</span> <span class="pun">}</span> |
Handling errors
To capture errors so they don’t result in uncaught exceptions, you can register a catchError
handler on the Future, or (in an async
function) use try-catch:
1 2 3 4 5 6 7 8 9 |
<span class="typ">Future</span><span class="pln"> main</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> config </span><span class="pun">=</span> <span class="typ">File</span><span class="pun">(</span><span class="str">'config.txt'</span><span class="pun">);</span> <span class="kwd">try</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> contents </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> config</span><span class="pun">.</span><span class="pln">readAsString</span><span class="pun">();</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">contents</span><span class="pun">);</span> <span class="pun">}</span> <span class="kwd">catch</span> <span class="pun">(</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">}</span> |
Streaming file contents
Use a Stream to read a file, a little at a time. You can use either the Stream API or await for
, part of Dart’s asynchrony support.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="kwd">import</span> <span class="str">'dart:io'</span><span class="pun">;</span> <span class="kwd">import</span> <span class="str">'dart:convert'</span><span class="pun">;</span> <span class="typ">Future</span><span class="pln"> main</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> config </span><span class="pun">=</span> <span class="typ">File</span><span class="pun">(</span><span class="str">'config.txt'</span><span class="pun">);</span> <span class="typ">Stream</span><span class="pun"><</span><span class="typ">List</span><span class="pun"><</span><span class="typ">int</span><span class="pun">>></span><span class="pln"> inputStream </span><span class="pun">=</span><span class="pln"> config</span><span class="pun">.</span><span class="pln">openRead</span><span class="pun">();</span> <span class="kwd">var</span><span class="pln"> lines </span><span class="pun">=</span><span class="pln"> utf8</span><span class="pun">.</span><span class="pln">decoder</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="pln">inputStream</span><span class="pun">).</span><span class="pln">transform</span><span class="pun">(</span><span class="typ">LineSplitter</span><span class="pun">());</span> <span class="kwd">try</span> <span class="pun">{</span> <span class="kwd">await</span> <span class="kwd">for</span> <span class="pun">(</span><span class="kwd">var</span><span class="pln"> line </span><span class="kwd">in</span><span class="pln"> lines</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Got ${line.length} characters from stream'</span><span class="pun">);</span> <span class="pun">}</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'file is now closed'</span><span class="pun">);</span> <span class="pun">}</span> <span class="kwd">catch</span> <span class="pun">(</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">e</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">}</span> |
Writing file contents
You can use an IOSink to write data to a file. Use the File openWrite()
method to get an IOSink that you can write to. The default mode, FileMode.write
, completely overwrites existing data in the file.
1 2 3 4 5 |
<span class="kwd">var</span><span class="pln"> logFile </span><span class="pun">=</span> <span class="typ">File</span><span class="pun">(</span><span class="str">'log.txt'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> sink </span><span class="pun">=</span><span class="pln"> logFile</span><span class="pun">.</span><span class="pln">openWrite</span><span class="pun">();</span><span class="pln"> sink</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'FILE ACCESSED ${DateTime.now()}\n'</span><span class="pun">);</span> <span class="kwd">await</span><span class="pln"> sink</span><span class="pun">.</span><span class="pln">flush</span><span class="pun">();</span> <span class="kwd">await</span><span class="pln"> sink</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span> |
To add to the end of the file, use the optional mode
parameter to specify FileMode.append
:
1 |
<span class="kwd">var</span><span class="pln"> sink </span><span class="pun">=</span><span class="pln"> logFile</span><span class="pun">.</span><span class="pln">openWrite</span><span class="pun">(</span><span class="pln">mode</span><span class="pun">:</span> <span class="typ">FileMode</span><span class="pun">.</span><span class="pln">append</span><span class="pun">);</span> |
To write binary data, use add(List<int> data)
.
Listing files in a directory
Finding all files and subdirectories for a directory is an asynchronous operation. The list()
method returns a Stream that emits an object when a file or directory is encountered.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="typ">Future</span><span class="pln"> main</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> dir </span><span class="pun">=</span> <span class="typ">Directory</span><span class="pun">(</span><span class="str">'tmp'</span><span class="pun">);</span> <span class="kwd">try</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> dirList </span><span class="pun">=</span><span class="pln"> dir</span><span class="pun">.</span><span class="pln">list</span><span class="pun">();</span> <span class="kwd">await</span> <span class="kwd">for</span> <span class="pun">(</span><span class="typ">FileSystemEntity</span><span class="pln"> f </span><span class="kwd">in</span><span class="pln"> dirList</span><span class="pun">)</span> <span class="pun">{</span> <span class="kwd">if</span> <span class="pun">(</span><span class="pln">f </span><span class="kwd">is</span> <span class="typ">File</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Found file ${f.path}'</span><span class="pun">);</span> <span class="pun">}</span> <span class="kwd">else</span> <span class="kwd">if</span> <span class="pun">(</span><span class="pln">f </span><span class="kwd">is</span> <span class="typ">Directory</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Found dir ${f.path}'</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">}</span> <span class="pun">}</span> <span class="kwd">catch</span> <span class="pun">(</span><span class="pln">e</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">e</span><span class="pun">.</span><span class="pln">toString</span><span class="pun">());</span> <span class="pun">}</span> <span class="pun">}</span> |
Other common functionality
The File and Directory classes contain other functionality, including but not limited to:
- Creating a file or directory:
create()
in File and Directory - Deleting a file or directory:
delete()
in File and Directory - Getting the length of a file:
length()
in File - Getting random access to a file:
open()
in File
Refer to the API docs for File and Directory for a full list of methods.
HTTP clients and servers
The dart:io library provides classes that command-line apps can use for accessing HTTP resources, as well as running HTTP servers.
HTTP server
The HttpServer class provides the low-level functionality for building web servers. You can match request handlers, set headers, stream data, and more.
The following sample web server returns simple text information. This server listens on port 8888 and address 127.0.0.1 (localhost), responding to requests for the path /dart
. For any other path, the response is status code 404 (page not found).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<span class="typ">Future</span><span class="pln"> main</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="kwd">final</span><span class="pln"> requests </span><span class="pun">=</span> <span class="kwd">await</span> <span class="typ">HttpServer</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'localhost'</span><span class="pun">,</span> <span class="lit">8888</span><span class="pun">);</span> <span class="kwd">await</span> <span class="kwd">for</span> <span class="pun">(</span><span class="kwd">var</span><span class="pln"> request </span><span class="kwd">in</span><span class="pln"> requests</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> processRequest</span><span class="pun">(</span><span class="pln">request</span><span class="pun">);</span> <span class="pun">}</span> <span class="pun">}</span> <span class="typ">void</span><span class="pln"> processRequest</span><span class="pun">(</span><span class="typ">HttpRequest</span><span class="pln"> request</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Got request for ${request.uri.path}'</span><span class="pun">);</span> <span class="kwd">final</span><span class="pln"> response </span><span class="pun">=</span><span class="pln"> request</span><span class="pun">.</span><span class="pln">response</span><span class="pun">;</span> <span class="kwd">if</span> <span class="pun">(</span><span class="pln">request</span><span class="pun">.</span><span class="pln">uri</span><span class="pun">.</span><span class="pln">path </span><span class="pun">==</span> <span class="str">'/dart'</span><span class="pun">)</span> <span class="pun">{</span><span class="pln"> response </span><span class="pun">..</span><span class="pln">headers</span><span class="pun">.</span><span class="pln">contentType </span><span class="pun">=</span> <span class="typ">ContentType</span><span class="pun">(</span> <span class="str">'text'</span><span class="pun">,</span> <span class="str">'plain'</span><span class="pun">,</span> <span class="pun">)</span> <span class="pun">..</span><span class="pln">write</span><span class="pun">(</span><span class="str">'Hello from the server'</span><span class="pun">);</span> <span class="pun">}</span> <span class="kwd">else</span> <span class="pun">{</span><span class="pln"> response</span><span class="pun">.</span><span class="pln">statusCode </span><span class="pun">=</span> <span class="typ">HttpStatus</span><span class="pun">.</span><span class="pln">notFound</span><span class="pun">;</span> <span class="pun">}</span><span class="pln"> response</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span> <span class="pun">}</span> |
HTTP client
The HttpClient class helps you connect to HTTP resources from your Dart command-line or server-side application. You can set headers, use HTTP methods, and read and write data. The HttpClient class does not work in browser-based apps. When programming in the browser, use the dart:html HttpRequest class. Here’s an example of using HttpClient:
1 2 3 4 5 6 7 8 9 |
<span class="typ">Future</span><span class="pln"> main</span><span class="pun">()</span> <span class="kwd">async</span> <span class="pun">{</span> <span class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span> <span class="typ">Uri</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">'http://localhost:8888/dart'</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> httpClient </span><span class="pun">=</span> <span class="typ">HttpClient</span><span class="pun">();</span> <span class="kwd">var</span><span class="pln"> request </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> httpClient</span><span class="pun">.</span><span class="pln">getUrl</span><span class="pun">(</span><span class="pln">url</span><span class="pun">);</span> <span class="kwd">var</span><span class="pln"> response </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> request</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span> <span class="kwd">var</span><span class="pln"> data </span><span class="pun">=</span> <span class="kwd">await</span><span class="pln"> utf8</span><span class="pun">.</span><span class="pln">decoder</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="pln">response</span><span class="pun">).</span><span class="pln">toList</span><span class="pun">();</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Response ${response.statusCode}: $data'</span><span class="pun">);</span><span class="pln"> httpClient</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span> <span class="pun">}</span> |
More information
This page showed how to use the major features of the dart:io library. Besides the APIs discussed in this section, the dart:io library also provides APIs for processes, sockets, and web sockets. For more information about server-side and command-line app development, see the server-side Dart overview.
For information on other dart:* libraries, see the library tour.
Summary
This page introduced you to the most commonly used functionality in Dart’s built-in libraries. It didn’t cover all the built-in libraries, however. Others that you might want to look into include dart:collection and dart:typed_data, as well as platform-specific libaries like the Dart web development libraries and the Flutter libraries.
You can get yet more libraries by using the pub package manager. The collection, crypto, http, intl, and test libraries are just a sampling of what you can install using pub.
To learn more about the Dart language, see the language tour.