On this page22 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. What Is a Package?
- 2. Your Project Is Already a Package
- 3. package: Imports
- 4. package: vs Relative Imports
- 5. pub.dev — Where Packages Live
- 6. Adding a Package with dart pub add
- 7. .sum, .max, .min and .average
- 8. firstWhereOrNull
- 9. Empty Lists: max vs maxOrNull
- 10. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 103 — Dart Packages
| Category | 17 — Libraries & Packages |
| Lecture | 103 of 140 |
| Estimated video length | 10 min |
| Target | Dart 3.12.2 |
| Level | Intermediate |
Lists still have no
.sumor.max, anddart:libraries can't help. Thousands of ready-made libraries are shared as packages — and one command adds them to your project.
Contents
Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways
Every output and error message in this lecture is real. Each one was produced by running the commands and code shown on Dart 3.12.2.
dart pub addneeds an internet connection.
Prerequisites
Students should already understand, from Lectures 002–102:
- creating a project with
dart createand running it withdart run(Lecture 002) fold,reduceand the missing.sum(Lecture 044)firstWhereon a list (Lecture 042)- extension methods (Lecture 069)
import,as,showandhide(Lecture 101)- splitting your code into library files (Lecture 102)
Connection With Previous Lectures
In Lecture 044, Dart refused marks.sum, and in Lecture 101 dart:math only gave us a max
for two numbers:
import 'dart:math';
void main() {
var marks = [80, 75, 85];
var total = marks.fold(0, (sum, mark) => sum + mark);
print(marks.reduce(max));
print(total);
}85
240It works, but every programmer in the world writes these same lines again and again. Someone
has already written .sum and .max properly and shared them. We need a way to bring that
shared code into our project.
Learning Objectives
By the end of this lecture you will be able to:
- Explain what a package is and how it differs from a library
- Recognize the parts of a package:
pubspec.yamlandlib/ - Find packages on pub.dev
- Import with
package:instead of a relative path - Add a package with
dart pub add - Use
.sum,.max,.min,.averageandfirstWhereOrNullfrompackage:collection - Recognize the error messages Dart produces for common package mistakes
1. What Is a Package?
A package is a folder of Dart libraries with a pubspec.yaml file that gives it a name.
The libraries others may use live in its lib/ folder.
Analogy — if a library is one book, a package is a boxed set: a label on the box (
pubspec.yaml) and the books inside (lib/). You order the whole box, then read the books you need.
2. Your Project Is Already a Package
In Lecture 002, dart create built this layout:
dart create marks_app pubspec.yaml
bin/marks_app.dart
lib/marks_app.dart
test/marks_app_test.dartIt has a pubspec.yaml and a lib/ folder — so marks_app is a package. Its name comes
from the first line of pubspec.yaml:
name: marks_appbin/ holds the program you run; lib/ holds code to share. We will read the rest of
pubspec.yaml in Lecture 104.
3. package: Imports
Open bin/marks_app.dart. Its first line imports the project's own lib/ file:
import 'package:marks_app/marks_app.dart' as marks_app;
void main(List<String> arguments) {
print('Hello world: ${marks_app.calculate()}!');
}Hello world: 42!Read package:marks_app/marks_app.dart as "in the package marks_app, open the file
marks_app.dart inside its lib/ folder". You never write lib/ — package: always points
there.
4. package: vs Relative Imports
A relative import gives a path from the current file, like 'bank_account.dart' in
Lecture 057. From bin/ you could reach lib/ with ../lib/:
import '../lib/marks_app.dart';
void main() {
print(calculate());
}42It runs, but dart analyze objects:
info - bin/marks_app.dart:1:8 - Can't use a relative path to import a library in 'lib'. Try
fixing the relative path or changing the import to a 'package:' import. -
avoid_relative_lib_importsThe rule: from outside lib/ (bin/, test/), import lib/ files with package:.
Inside lib/, relative imports between neighbours are fine.
5. pub.dev — Where Packages Live
pub.dev is Dart's official website for sharing packages. Search for a word like "collection" and each result shows:
- likes — how many developers bookmarked it
- pub points — a quality score out of 160 (documentation, formatting, analysis)
- downloads — how widely it is used
- a publisher badge —
dart.devmeans the Dart team itself maintains it
collection is published by dart.dev. It adds extra helpers for lists, sets and maps.
6. Adding a Package with dart pub add
Inside the project folder, run:
dart pub add collectionResolving dependencies...
Downloading packages...
collection 1.19.1 (from transitive dependency to direct dependency)
Changed 1 dependency!The tools dart create installed already used collection behind the scenes — that is the
"transitive dependency". Now our own code depends on it directly. A new package would
simply show as + name version. pubspec.yaml gained one line:
dependencies:
collection: ^1.19.1We will explain ^1.19.1 and pubspec.lock in Lectures 104–105.
7. .sum, .max, .min and .average
Import the package's main library, and lists of numbers gain new getters:
import 'package:collection/collection.dart';
void main() {
var marks = [80, 75, 85];
print(marks.sum);
print(marks.max);
print(marks.min);
print(marks.average);
}240
85
75
80.0These are extension getters (Lecture 069) written by the Dart team. .average is always a
double.
8. firstWhereOrNull
firstWhere crashes when nothing matches:
void main() {
var names = ['Ali', 'Sara', 'Zayan'];
print(names.firstWhere((n) => n.startsWith('H')));
}Unhandled exception:
Bad state: No elementfirstWhereOrNull from collection returns null instead, so ?? can supply a fallback:
import 'package:collection/collection.dart';
void main() {
var names = ['Ali', 'Sara', 'Zayan'];
print(names.firstWhereOrNull((n) => n.startsWith('S')));
print(names.firstWhereOrNull((n) => n.startsWith('H')) ?? 'nobody');
}Sara
nobody9. Empty Lists: max vs maxOrNull
.sum of an empty list is 0, but .max has no answer and throws. maxOrNull and
minOrNull return null instead:
import 'package:collection/collection.dart';
void main() {
var marks = <int>[];
print(marks.sum);
print(marks.maxOrNull);
}0
nullCalling marks.max here gives Bad state: No element, just like reduce in Lecture 044.
10. A Real-World Example
A class summary using the project's package:collection dependency:
import 'package:collection/collection.dart';
void main() {
var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 44, 'Hina': 88};
var total = marks.values.sum;
var average = marks.values.average;
var best = marks.values.max;
var topStudent = marks.keys.firstWhereOrNull((n) => marks[n] == best);
var failing = marks.keys.firstWhereOrNull((n) => marks[n]! < 50);
print('Total: $total, Average: $average');
print('Top: $topStudent with $best');
print('Needs help: ${failing ?? 'no one'}');
}Total: 299, Average: 74.75
Top: Sara with 95
Needs help: ZayanNo fold, no reduce, no dart:math — one import, and the code says what it means.
Code Examples
Run each example from the bin/ folder of a project where you ran dart pub add collection.
Example 1 — Sum
import 'package:collection/collection.dart';
void main() {
var scores = [12, 30, 8];
print('Sum: ${scores.sum}');
}Sum: 50Example 2 — Max and Min
import 'package:collection/collection.dart';
void main() {
var ages = [21, 6, 18];
print('Oldest: ${ages.max}');
print('Youngest: ${ages.min}');
}Oldest: 21
Youngest: 6Example 3 — Average
import 'package:collection/collection.dart';
void main() {
var steps = [4000, 6500, 5500];
print(steps.average);
}5333.333333333333Example 4 — firstWhereOrNull Finds a Match
import 'package:collection/collection.dart';
void main() {
var cities = ['Lahore', 'Karachi', 'Quetta'];
print(cities.firstWhereOrNull((c) => c.length > 6));
}KarachiExample 5 — No Match, Safe Fallback
import 'package:collection/collection.dart';
void main() {
var cities = ['Lahore', 'Karachi', 'Quetta'];
var city = cities.firstWhereOrNull((c) => c.startsWith('Z'));
print(city ?? 'not found');
}not foundExample 6 — A package: Import of Your Own Code
import 'package:marks_app/marks_app.dart';
void main() {
print('Answer: ${calculate()}');
}Answer: 42Example 7 — Student Marks
import 'package:collection/collection.dart';
void main() {
var marks = [55, 91, 78, 66];
print('Total: ${marks.sum}');
print('Average: ${marks.average}');
print('Gap: ${marks.max - marks.min}');
}Total: 290
Average: 72.5
Gap: 36How it works
.sumreplacesfold(0, (sum, mark) => sum + mark)..maxand.minreplacereduce(max)andreduce(min).
Example 8 — Shopping Total
import 'package:collection/collection.dart';
void main() {
var cart = {'Notebook': 500, 'Pen': 50, 'Bag': 1500};
print('Items: ${cart.length}');
print('Total: ${cart.values.sum}');
print('Priciest: ${cart.values.max}');
}Items: 3
Total: 2050
Priciest: 1500How it works
cart.valuesis anIterable<int>; the getters work on any iterable of numbers, not only lists.
Example 9 — Bank Balance
import 'package:collection/collection.dart';
void main() {
var history = [1000, -200, 500, -50];
var balance = history.sum;
var bigWithdrawal = history.firstWhereOrNull((t) => t < -100);
print('Balance: $balance');
print('First big withdrawal: ${bigWithdrawal ?? 'none'}');
}Balance: 1250
First big withdrawal: -200How it works
- Deposits are positive and withdrawals negative, so
.sumis the balance. firstWhereOrNullfinds the first amount below-100, ornull.
Example 10 — Temperatures
import 'package:collection/collection.dart';
void main() {
var week = [29.5, 31.0, 30.5, 32.0, 28.0];
print('Hottest: ${week.max}');
print('Average: ${week.average.toStringAsFixed(1)}');
}Hottest: 32.0
Average: 30.2How it works
- The getters work on
doublelists too;.maxstays adouble. toStringAsFixed(1)rounds30.2for display.
Common Beginner Mistakes
1. Importing a package you never added
// import 'package:intl/intl.dart'; // ✗ intl is not in pubspec.yamlError: Couldn't resolve the package 'intl' in 'package:intl/intl.dart'.Run dart pub add intl first.
2. Running a package import outside a project
A single file in a folder with no pubspec.yaml has no packages, so even collection fails:
Error: Couldn't resolve the package 'collection' in 'package:collection/collection.dart'.Put the file in a project's bin/ folder.
3. Misspelling the package name
dart pub add colectionBecause marks_app depends on colection any which doesn't exist (could not find package
colection at https://pub.dev), version solving failed.4. Forgetting the import
void main() {
var marks = [80, 75];
// print(marks.sum); // ✗ no import 'package:collection/collection.dart'
}Error: The getter 'sum' isn't defined for the type 'List<int>'.Adding a package does not import it — every file that uses it needs the import line.
5. Writing lib/ in a package: import
package:marks_app/lib/marks_app.dart is wrong. package: already means "inside lib/":
write package:marks_app/marks_app.dart.
6. Calling .max on a list that may be empty
It throws Bad state: No element. Use maxOrNull with ??.
Best Practices
- Check
dart:libraries first; add a package only when they can't do the job. - Prefer well-known packages: a verified publisher, high pub points, recent updates.
- Add packages with
dart pub add, not by hand-editingpubspec.yaml. - Use
package:imports frombin/andtest/intolib/. - Put
dart:imports first, thenpackage:imports, then relative ones. - Use
firstWhereOrNullandmaxOrNullwhen "nothing found" is a normal result.
Mini Challenge
Zayan's quiz scores are [7, 9, 4, 10, 8]. Using package:collection, print the total, the
best score, and the first score below 5.
Your program should print exactly:
Total: 38
Best: 10
First low score: 4Try it yourself before opening the solution.
Show solution
import 'package:collection/collection.dart';
void main() {
var scores = [7, 9, 4, 10, 8];
print('Total: ${scores.sum}');
print('Best: ${scores.max}');
print('First low score: ${scores.firstWhereOrNull((s) => s < 5)}');
}Total: 38
Best: 10
First low score: 4How it works
.sumand.maxcome from the package's extensions on numbers.firstWhereOrNullreturns the first match,4.
Practice Questions
Work through these in order — they run from beginner to application to challenge.
Run them inside a project that has collection added.
Beginner
- Print the sum of
[3, 6, 9]with.sum. - Print the largest and smallest of
[45, 12, 78, 33]. - Write the
importline forpackage:collection, and the command that adds it to a project.
Application
-
Print the average of
[60, 70, 95]. -
From
['Ali', 'Sara', 'Hina'], print the first name containing'n', ornone. -
From
[15, 22, 9], print the first number above30, ornone. -
Print
maxOrNullof an empty<int>[], followed by.sumof the same list. -
This file in
bin/importslib/marks_app.dartthe discouraged way. Rewrite the import:import '../lib/marks_app.dart';
Challenge
- For the prices
{'Pen': 50, 'Book': 450, 'Bag': 1500}, printTotal: 2000andAverage: 666.67. - Sara's deposits are
[2000, 500, 750]and her withdrawals[300, 1200]. Print her balance and her biggest single withdrawal.
Practice Answers
Question 1 — Solution
import 'package:collection/collection.dart';
void main() {
print([3, 6, 9].sum);
}18Question 2 — Solution
import 'package:collection/collection.dart';
void main() {
var values = [45, 12, 78, 33];
print(values.max);
print(values.min);
}78
12Question 3 — Solution
import 'package:collection/collection.dart';dart pub add collectionQuestion 4 — Solution
import 'package:collection/collection.dart';
void main() {
print([60, 70, 95].average);
}75.0Question 5 — Solution
import 'package:collection/collection.dart';
void main() {
var names = ['Ali', 'Sara', 'Hina'];
print(names.firstWhereOrNull((n) => n.contains('n')) ?? 'none');
}HinaQuestion 6 — Solution
import 'package:collection/collection.dart';
void main() {
var numbers = [15, 22, 9];
print(numbers.firstWhereOrNull((n) => n > 30) ?? 'none');
}noneQuestion 7 — Solution
import 'package:collection/collection.dart';
void main() {
var empty = <int>[];
print(empty.maxOrNull);
print(empty.sum);
}null
0Question 8 — Solution
import 'package:marks_app/marks_app.dart';package: points into lib/ from anywhere in the project, and dart analyze stops warning.
Question 9 — Solution
import 'package:collection/collection.dart';
void main() {
var prices = {'Pen': 50, 'Book': 450, 'Bag': 1500};
print('Total: ${prices.values.sum}');
print('Average: ${prices.values.average.toStringAsFixed(2)}');
}Total: 2000
Average: 666.67Question 10 — Solution
import 'package:collection/collection.dart';
void main() {
var deposits = [2000, 500, 750];
var withdrawals = [300, 1200];
print('Balance: ${deposits.sum - withdrawals.sum}');
print('Biggest withdrawal: ${withdrawals.max}');
}Balance: 1750
Biggest withdrawal: 1200Quick Revision
- What two things make a folder a package?
- Is a project made by
dart createa package? - Which folder does
package:name/file.dartpoint into? - Where do you find shared Dart packages?
- Which command adds
collectionto a project? - Does adding a package import it into every file?
- What does
firstWhereOrNullreturn when nothing matches? - Why use
maxOrNullinstead ofmax?
Key Takeaways
- A package is a
pubspec.yamlplus libraries inlib/; everydart createproject is one. package:name/file.dartimportslib/file.dartof packagename.- From
bin/andtest/, importlib/files withpackage:, not../lib/. - pub.dev hosts shared packages; check likes, pub points and the publisher.
dart pub add namedownloads a package and records it inpubspec.yaml.- Each file that uses a package still needs its
importline. package:collectionadds.sum,.max,.min,.average,firstWhereOrNullandmaxOrNull.
What's Next?
Lecture 104 — pubspec.yaml. dart pub add quietly wrote a line into pubspec.yaml. Next
we will read that file line by line — the package name, the SDK version, and what
collection: ^1.19.1 really promises.