Replace LinkedHashMap.* with Map.*, which _is_ Linked (#170713)

Pre-work to make it easier to land
https://github.com/flutter/flutter/pull/170435.

The default `Map` constructor is and always has been a `LinkedHashMap`:

https://api.dart.dev/dart-core/Map/Map.html

This change make its easier to relax the type annotation rules in a
future PR.

/cc @eernstg
This commit is contained in:
Matan Lurey 2025-06-16 19:46:22 -07:00 committed by GitHub
parent b42c00bca8
commit 753e961332
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 49 additions and 66 deletions

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:collection';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -110,7 +108,7 @@ Future<void> pumpDeferredLibraries() {
class Demos {
static Map<String?, GalleryDemo> asSlugToDemoMap(BuildContext context) {
final GalleryLocalizations localizations = GalleryLocalizations.of(context)!;
return LinkedHashMap<String?, GalleryDemo>.fromIterable(
return Map<String?, GalleryDemo>.fromIterable(
all(localizations),
// ignore: avoid_dynamic_calls
key: (dynamic demo) => demo.slug as String?,

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:collection';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localized_locales/flutter_localized_locales.dart';
@ -100,9 +98,9 @@ class _SettingsPageState extends State<SettingsPage> {
/// Create a sorted — by native name – map of supported locales to their
/// intended display string, with a system option as the first element.
LinkedHashMap<Locale, DisplayOption> _getLocaleOptions() {
final LinkedHashMap<Locale, DisplayOption> localeOptions =
LinkedHashMap<Locale, DisplayOption>.of(<Locale, DisplayOption>{
Map<Locale, DisplayOption> _getLocaleOptions() {
final Map<Locale, DisplayOption> localeOptions =
Map<Locale, DisplayOption>.of(<Locale, DisplayOption>{
systemLocaleOption: DisplayOption(
GalleryLocalizations.of(context)!.settingsSystemDefault +
(deviceLocale != null
@ -123,7 +121,7 @@ class _SettingsPageState extends State<SettingsPage> {
compareAsciiUpperCase(l1.value.title, l2.value.title),
);
localeOptions.addAll(LinkedHashMap<Locale, DisplayOption>.fromEntries(displayLocales));
localeOptions.addAll(Map<Locale, DisplayOption>.fromEntries(displayLocales));
return localeOptions;
}
@ -138,7 +136,7 @@ class _SettingsPageState extends State<SettingsPage> {
SettingsListItem<double?>(
title: localizations.settingsTextScaling,
selectedOption: options.textScaleFactor(context, useSentinel: true),
optionsMap: LinkedHashMap<double?, DisplayOption>.of(<double?, DisplayOption>{
optionsMap: Map<double?, DisplayOption>.of(<double?, DisplayOption>{
systemTextScaleFactorOption: DisplayOption(localizations.settingsSystemDefault),
0.8: DisplayOption(localizations.settingsTextScalingSmall),
1.0: DisplayOption(localizations.settingsTextScalingNormal),
@ -154,15 +152,14 @@ class _SettingsPageState extends State<SettingsPage> {
SettingsListItem<CustomTextDirection?>(
title: localizations.settingsTextDirection,
selectedOption: options.customTextDirection,
optionsMap: LinkedHashMap<CustomTextDirection?, DisplayOption>.of(
<CustomTextDirection?, DisplayOption>{
CustomTextDirection.localeBased: DisplayOption(
localizations.settingsTextDirectionLocaleBased,
),
CustomTextDirection.ltr: DisplayOption(localizations.settingsTextDirectionLTR),
CustomTextDirection.rtl: DisplayOption(localizations.settingsTextDirectionRTL),
},
),
optionsMap:
Map<CustomTextDirection?, DisplayOption>.of(<CustomTextDirection?, DisplayOption>{
CustomTextDirection.localeBased: DisplayOption(
localizations.settingsTextDirectionLocaleBased,
),
CustomTextDirection.ltr: DisplayOption(localizations.settingsTextDirectionLTR),
CustomTextDirection.rtl: DisplayOption(localizations.settingsTextDirectionRTL),
}),
onOptionChanged:
(CustomTextDirection? newTextDirection) => GalleryOptions.update(
context,
@ -187,14 +184,13 @@ class _SettingsPageState extends State<SettingsPage> {
SettingsListItem<TargetPlatform?>(
title: localizations.settingsPlatformMechanics,
selectedOption: options.platform,
optionsMap:
LinkedHashMap<TargetPlatform?, DisplayOption>.of(<TargetPlatform?, DisplayOption>{
TargetPlatform.android: DisplayOption('Android'),
TargetPlatform.iOS: DisplayOption('iOS'),
TargetPlatform.macOS: DisplayOption('macOS'),
TargetPlatform.linux: DisplayOption('Linux'),
TargetPlatform.windows: DisplayOption('Windows'),
}),
optionsMap: Map<TargetPlatform?, DisplayOption>.of(<TargetPlatform?, DisplayOption>{
TargetPlatform.android: DisplayOption('Android'),
TargetPlatform.iOS: DisplayOption('iOS'),
TargetPlatform.macOS: DisplayOption('macOS'),
TargetPlatform.linux: DisplayOption('Linux'),
TargetPlatform.windows: DisplayOption('Windows'),
}),
onOptionChanged:
(TargetPlatform? newPlatform) =>
GalleryOptions.update(context, options.copyWith(platform: newPlatform)),
@ -204,7 +200,7 @@ class _SettingsPageState extends State<SettingsPage> {
SettingsListItem<ThemeMode?>(
title: localizations.settingsTheme,
selectedOption: options.themeMode,
optionsMap: LinkedHashMap<ThemeMode?, DisplayOption>.of(<ThemeMode?, DisplayOption>{
optionsMap: Map<ThemeMode?, DisplayOption>.of(<ThemeMode?, DisplayOption>{
ThemeMode.system: DisplayOption(localizations.settingsSystemDefault),
ThemeMode.dark: DisplayOption(localizations.settingsDarkTheme),
ThemeMode.light: DisplayOption(localizations.settingsLightTheme),

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:collection';
import 'package:flutter/material.dart';
// Common constants between SlowMotionSetting and SettingsListItem.
@ -81,7 +79,7 @@ class SettingsListItem<T> extends StatefulWidget {
required this.isExpanded,
});
final LinkedHashMap<T, DisplayOption> optionsMap;
final Map<T, DisplayOption> optionsMap;
final String title;
final T selectedOption;
final ValueChanged<T> onOptionChanged;

View File

@ -106,7 +106,7 @@ class ObserverList<T> extends Iterable<T> {
///
/// * [ObserverList] for a list that is fast for small numbers of observers.
class HashedObserverList<T> extends Iterable<T> {
final LinkedHashMap<T, int> _map = LinkedHashMap<T, int>();
final Map<T, int> _map = <T, int>{};
/// Adds an item to the end of this list.
///

View File

@ -5,7 +5,6 @@
/// @docImport 'package:flutter/cupertino.dart';
library;
import 'dart:collection';
import 'dart:math' as math;
import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle, LineMetrics, SemanticsInputType, TextBox;
@ -1308,7 +1307,7 @@ class RenderEditable extends RenderBox
// can be re-used when [assembleSemanticsNode] is called again. This ensures
// stable ids for the [SemanticsNode]s of [TextSpan]s across
// [assembleSemanticsNode] invocations.
LinkedHashMap<Key, SemanticsNode>? _cachedChildNodes;
Map<Key, SemanticsNode>? _cachedChildNodes;
/// Returns a list of rects that bound the given selection, and the text
/// direction. The text direction is used by the engine to calculate
@ -1436,7 +1435,7 @@ class RenderEditable extends RenderBox
int placeholderIndex = 0;
int childIndex = 0;
RenderBox? child = firstChild;
final LinkedHashMap<Key, SemanticsNode> newChildCache = LinkedHashMap<Key, SemanticsNode>();
final Map<Key, SemanticsNode> newChildCache = <Key, SemanticsNode>{};
_cachedCombinedSemanticsInfos ??= combineSemanticsInfo(_semanticsInfo!);
for (final InlineSpanSemanticsInformation info in _cachedCombinedSemanticsInfos!) {
final TextSelection selection = TextSelection(

View File

@ -5,7 +5,6 @@
/// @docImport 'binding.dart';
library;
import 'dart:collection' show LinkedHashMap;
import 'dart:ui';
import 'package:flutter/foundation.dart';
@ -27,16 +26,13 @@ class _MouseState {
_MouseState({required PointerEvent initialEvent}) : _latestEvent = initialEvent;
// The list of annotations that contains this device.
//
// It uses [LinkedHashMap] to keep the insertion order.
LinkedHashMap<MouseTrackerAnnotation, Matrix4> get annotations => _annotations;
LinkedHashMap<MouseTrackerAnnotation, Matrix4> _annotations =
LinkedHashMap<MouseTrackerAnnotation, Matrix4>();
Map<MouseTrackerAnnotation, Matrix4> get annotations => _annotations;
Map<MouseTrackerAnnotation, Matrix4> _annotations = <MouseTrackerAnnotation, Matrix4>{};
LinkedHashMap<MouseTrackerAnnotation, Matrix4> replaceAnnotations(
LinkedHashMap<MouseTrackerAnnotation, Matrix4> value,
Map<MouseTrackerAnnotation, Matrix4> replaceAnnotations(
Map<MouseTrackerAnnotation, Matrix4> value,
) {
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> previous = _annotations;
final Map<MouseTrackerAnnotation, Matrix4> previous = _annotations;
_annotations = value;
return previous;
}
@ -93,12 +89,12 @@ class _MouseTrackerUpdateDetails with Diagnosticable {
/// The annotations that the device is hovering before the update.
///
/// It is never null.
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations;
final Map<MouseTrackerAnnotation, Matrix4> lastAnnotations;
/// The annotations that the device is hovering after the update.
///
/// It is never null.
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations;
final Map<MouseTrackerAnnotation, Matrix4> nextAnnotations;
/// The last event that the device observed before the update.
///
@ -232,11 +228,8 @@ class MouseTracker extends ChangeNotifier {
lastEvent.position != event.position;
}
LinkedHashMap<MouseTrackerAnnotation, Matrix4> _hitTestInViewResultToAnnotations(
HitTestResult result,
) {
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> annotations =
LinkedHashMap<MouseTrackerAnnotation, Matrix4>();
Map<MouseTrackerAnnotation, Matrix4> _hitTestInViewResultToAnnotations(HitTestResult result) {
final Map<MouseTrackerAnnotation, Matrix4> annotations = <MouseTrackerAnnotation, Matrix4>{};
for (final HitTestEntry entry in result.path) {
final Object target = entry.target;
if (target is MouseTrackerAnnotation) {
@ -251,12 +244,12 @@ class MouseTracker extends ChangeNotifier {
//
// If the device is not connected or not a mouse, an empty map is returned
// without calling `hitTest`.
LinkedHashMap<MouseTrackerAnnotation, Matrix4> _findAnnotations(_MouseState state) {
Map<MouseTrackerAnnotation, Matrix4> _findAnnotations(_MouseState state) {
final Offset globalPosition = state.latestEvent.position;
final int device = state.device;
final int viewId = state.latestEvent.viewId;
if (!_mouseStates.containsKey(device)) {
return LinkedHashMap<MouseTrackerAnnotation, Matrix4>();
return <MouseTrackerAnnotation, Matrix4>{};
}
return _hitTestInViewResultToAnnotations(_hitTestInView(globalPosition, viewId));
@ -341,12 +334,13 @@ class MouseTracker extends ChangeNotifier {
final _MouseState targetState = _mouseStates[device] ?? existingState!;
final PointerEvent lastEvent = targetState.replaceLatestEvent(event);
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations =
final Map<MouseTrackerAnnotation, Matrix4> nextAnnotations =
event is PointerRemovedEvent
? LinkedHashMap<MouseTrackerAnnotation, Matrix4>()
? <MouseTrackerAnnotation, Matrix4>{}
: _hitTestInViewResultToAnnotations(result);
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations = targetState
.replaceAnnotations(nextAnnotations);
final Map<MouseTrackerAnnotation, Matrix4> lastAnnotations = targetState.replaceAnnotations(
nextAnnotations,
);
_handleDeviceUpdate(
_MouseTrackerUpdateDetails.byPointerEvent(
@ -374,11 +368,10 @@ class MouseTracker extends ChangeNotifier {
_deviceUpdatePhase(() {
for (final _MouseState dirtyState in _mouseStates.values) {
final PointerEvent lastEvent = dirtyState.latestEvent;
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations = _findAnnotations(
dirtyState,
final Map<MouseTrackerAnnotation, Matrix4> nextAnnotations = _findAnnotations(dirtyState);
final Map<MouseTrackerAnnotation, Matrix4> lastAnnotations = dirtyState.replaceAnnotations(
nextAnnotations,
);
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations = dirtyState
.replaceAnnotations(nextAnnotations);
_handleDeviceUpdate(
_MouseTrackerUpdateDetails.byNewFrame(
@ -407,8 +400,8 @@ class MouseTracker extends ChangeNotifier {
static void _handleDeviceUpdateMouseEvents(_MouseTrackerUpdateDetails details) {
final PointerEvent latestEvent = details.latestEvent;
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations = details.lastAnnotations;
final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations = details.nextAnnotations;
final Map<MouseTrackerAnnotation, Matrix4> lastAnnotations = details.lastAnnotations;
final Map<MouseTrackerAnnotation, Matrix4> nextAnnotations = details.nextAnnotations;
// Order is important for mouse event callbacks. The
// `_hitTestInViewResultToAnnotations` returns annotations in the visual order

View File

@ -7,7 +7,6 @@
/// @docImport 'editable.dart';
library;
import 'dart:collection';
import 'dart:math' as math;
import 'dart:ui'
as ui
@ -1268,7 +1267,7 @@ class RenderParagraph extends RenderBox
// can be re-used when [assembleSemanticsNode] is called again. This ensures
// stable ids for the [SemanticsNode]s of [TextSpan]s across
// [assembleSemanticsNode] invocations.
LinkedHashMap<Key, SemanticsNode>? _cachedChildNodes;
Map<Key, SemanticsNode>? _cachedChildNodes;
@override
void assembleSemanticsNode(
@ -1285,7 +1284,7 @@ class RenderParagraph extends RenderBox
int placeholderIndex = 0;
int childIndex = 0;
RenderBox? child = firstChild;
final LinkedHashMap<Key, SemanticsNode> newChildCache = LinkedHashMap<Key, SemanticsNode>();
final Map<Key, SemanticsNode> newChildCache = <Key, SemanticsNode>{};
_cachedCombinedSemanticsInfos ??= combineSemanticsInfo(_semanticsInfo!);
for (final InlineSpanSemanticsInformation info in _cachedCombinedSemanticsInfos!) {
final TextSelection selection = TextSelection(