Dart Packages, Imports, and Futures
# Packages and Imports
When building applications with Dart, a .dart
file is called a library. Think of a library just like a JavaScript module.
In dart you can import libraries and packages. A Dart package is similar to a Node Module that you would install with NPM or Yarn.
A package is basically a folder that contains a pubspec.yaml
file plus a lib
folder that contains at least one .dart
file that has a main()
method. When we build Flutter apps, our first file
will be /lib/main.dart
.
# Imports
When importing libraries or packages into a .dart
file, you use the keyword import
at the top of the file. You can import as many as you need.
Every Dart file (plus its parts) is a library, even if it doesn’t use a library directive.
Importing a library generally means that you are importing another .dart
file for your current file to use. The value that you are importing should be wrapped in double or single quotation marks and
prefixed with package:
, if it is a package that you are getting from pub.dev
and including in your pubspec.yaml
, OR dart:
if it is one of the built-in packages, OR just a relative URL.
The only required argument to import is a URI specifying the library. For built-in libraries, the URI has the special dart:
scheme. For other libraries, you can use a file system path or the
package:
scheme. The package
: scheme specifies libraries provided by a package manager such as the pub tool.
Most of the time you will get the package with the terminal command pub get <package>
. This will add it to the pubspec.yaml file for you.
We can add package files to our project too. Basically a package is a folder that contains a pubspec.yaml
file. So, you can create local packages inside your projects and import them using your own
package name like this:
import 'package:my_project_name/my_code.dart';
This will give you direct access to everything inside my_code.dart
except for variables that have been marked as private by starting their names with underscores.
If you just have files inside of the /lib
folder, the simplest thing to do is to import them via a relative url.
import '../lib/somefile.dart';
Reference for imports and libraries
# Built-in Dart Libraries
Dart keeps projects small and efficient by not including everything that the language can do automatically. There is a core to the language that you can always use, but there are also additional built-in libraries that you can include by importing them at the top of your file.
See the whole list of Dart core libraries.
The dart:core
library is automatically available in every .dart
file.
The dart:async
library lets us work with Futures
(the Dart version of Promises). The dart:convert
library lets you work with JSON files. The dart:io
library lets you work with HTTP, files, and
sockets. The dart:math
library lets you work with Mathematical functions, constants, and random numbers.
Say you want to generate a Random integer between 50 and 100, inclusive. You will need to import the dart:math
library at the top of your file.
import 'dart:math';
void main(){
int min = 50;
int max = 100;
int range = max - min;
int randy = Random().nextInt(range) + min;
print('Your random number is $randy');
}
2
3
4
5
6
7
8
9
Here is the reference for the Random number generator.
# PubDev Packages
If you are importing an external package, then you will need to add it as a dependency to your pubspec.yaml
file.
The Pub.dev website is the official repository for Dart and Flutter packages. You will find practically every package you could need for a Dart or Flutter project on this site. You can have your own packages hosted elsewhere, but the standard practice is to publish them to the Pub Dev website.
Say for example you want to generate a uuid to use in your app. If you go to the Pub Dev website and search for uuid, then you will see a list of ranked results. The top result is this package.
At the top of the page you can see that the current version number is 3.0.7
. Below that is a menu bar with the links: Readme | Changelog | Example | Installing | Versions | Scores
.
Click the Installing
link for instructions and details. From the Terminal in VSCode, run:
dart pub add uuid
This command will add the package uuid
to your pubspec.yaml
file. Typically VSCode will download the package into your project when you save a change to pubspec.yaml
. If you open your pubspec
file you will now see this package listed under dependencies.
dependencies:
uuid: ^3.0.7
2
To add the files to your project, if VSCode did not already do this, then you can run dart pub get
, which will download and save the dependency packages from pubspec.yaml
.
The actual package files are not saved in your project folder. If you want to find the actual package files, you can look in ~/.pub-cache/hosted/pub.dev/
and look for the folder named for the
package and its version.
# Futures
In Dart, Futures
are the equivalent of JavaScript Promises
. They are part of the dart:async
built-in library.
anAsyncMethod().then((aReturnValue){
return 'some value';
}).then((aReturnValue){
//chained then methods just like JavaScript
})
2
3
4
5
Dart also has the async
and await
keywords which work just like they do in JavaScript.
void main() async {
final response = await http.read(someuri); //gets the headers
}
2
3
The Dart equivalent of Promise.all(arrayOfPromises)
is Future.wait(arrayOfFutures)
.
A useful feature that Dart has, is a built-in method delayed
for creating an asynchronous delay before making an asynchronous method call.
Future.delayed(
const Duration(seconds: 2),
() => 'Large Latte',
);
2
3
4
# Dart HTTP Requests
In Dart, you need to import the dart:http
package to be able to make the equivalent of JavaScript fetch
calls. If you are fetching JSON files then you will also need to import the dart:convert
package to convert between JSON and actual JSON data types.
Remember to add these to your project with the Terminal commands dart pub add http
and dart pub add convert
.
import 'package:http/http.dart' as http;
import 'dart:convert' as convert;
void main() async{
try{
var uri = Uri.parse('https://dart.dev/f/packages/http.json');
final info = await http.read(uri); //info about the response
final responseG = await http.get(uri); // http get request
final responseP = await http.post(uri); // http post request
}catch(err){
print('Failed http request $uri');
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Learn more about working with and encoding URIs here
Learn more about making Http Requests here
Here is the link to the HTTP package
# Working with JSON
The dart:convert
built-in library is required when you want to convert a JSON string to native Dart datatypes or vice versa.
import 'dart:convert' as convert;
var jsonString = '''
[
{"score": 40},
{"score": 80}
]
''';
var scores = convert.jsonDecode(jsonString);
assert(scores is List); // this passes so the code continues. scores is a List
var firstScore = scores[0]; // 40
assert(firstScore is Map); // scores[0] is a Map
assert(firstScore['score'] == 40); // scores[0]['score'] is 40
2
3
4
5
6
7
8
9
10
11
12
13
With the dart:convert
package imported we have access to the jsonDecode
and jsonEncode
methods. In the example above the String is being converted into a Dart List
.
When you use a method like http.get()
and get an HTTP Response object, which will have properties including a body
and a statusCode
. We can use the jsonDecode
method on the body like this:
var url = Uri.parse('https://jsonplaceholder.typicode.com/users/');
var response = await http.get(url);
if (response.statusCode == 200) {
var jsonResponse = convert.jsonDecode(response.body) as List<dynamic>;
var itemCount = jsonResponse.length;
print('Number of books about http: $itemCount.');
} else {
print('Request failed with status: ${response.statusCode}.');
}
2
3
4
5
6
7
8
9
The as List<dynamic>
means that we know our JSON string contains a List
, and that every item in the List
can be any data type, to be dynamically determined as converted.