dispose method
Detaches before disposing so a still-attached controller can't fire notifyListeners after disposal (its planner normally detaches it first, but disposal order isn't guaranteed).
Implementation
@override
void dispose() {
detach();
super.dispose();
}