Какую цветовую систему использует флаттер и почему мы используем `const Color` вместо`new Color`

Сегодня я пришел к следующему фрагменту кода, который реализует градиент во флаттере

return new Container(
  ...
  decoration: new BoxDecoration(
    gradient: new LinearGradient(
      colors: [
        const Color(0xFF3366FF), 
        const Color(0xFF00CCFF),
      ]
      begin: const FractionalOffset(0.0, 0.0),
      end: const FractionalOffset(1.0, 0.0),
      stops: [0.0, 1.0],
      tileMode: TileMode.clamp
    ),
  ),
),

И это подняло 2 вопроса:

1) Что такое цветовая система 0xFF3366FF этот? это выглядит несколько похоже на HEX, но это не так.

2) Почему мы используем const за const Color() в отличие от new Color() Я понимаю, что между ними по-разному, но const здесь кажется мне неинтуитивным, я ожидаю, что это создаст new Color() экземпляр класса, аналогично тому, как мы используем new Text("Some text"), Если это должно быть постоянным, почему нет TileMode.clamp также const?

4 ответа

Решение

Из источника Флаттер

class Color {
  /// Construct a color from the lower 32 bits of an [int].
  ///
  /// The bits are interpreted as follows:
  ///
  /// * Bits 24-31 are the alpha value.
  /// * Bits 16-23 are the red value.
  /// * Bits 8-15 are the green value.
  /// * Bits 0-7 are the blue value.
  ///
  /// In other words, if AA is the alpha value in hex, RR the red value in hex,
  /// GG the green value in hex, and BB the blue value in hex, a color can be
  /// expressed as `const Color(0xAARRGGBB)`.
  ///
  /// For example, to get a fully opaque orange, you would use `const
  /// Color(0xFFFF9000)` (`FF` for the alpha, `FF` for the red, `90` for the
  /// green, and `00` for the blue).
  const Color(int value) : value = value & 0xFFFFFFFF;

const экземпляры канонизированы.

Если у вас есть несколько const Color(0xFF00CCFF) в вашем коде будет создан только один экземпляр.

const экземпляры оцениваются во время компиляции. В виртуальной машине Dart это происходит, когда код загружается, но в рабочей среде Flutter используется компиляция AoT, поэтому значения const обеспечивают небольшое повышение производительности.

Смотрите также Как на самом деле работает const конструктор?

Как объясняется принятым ответом, const конструкторы - это небольшая оптимизация.

В дротик const MyObject(42) будет выделяться только один раз, даже если вы вызываете его сотни раз. Что означает меньшее выделение памяти> быстрее


Но разве это не незначительная оптимизация?

Ну, с точки зрения дротика, да. Но мы здесь трепетали. У нас также есть дерево виджетов, которое также может использовать const Конструкторы. Это означает, что мы могли бы изменить ваш пример кода на что-то вроде этого:

return const DecoratedBox(
  decoration: const BoxDecoration(
    gradient: const LinearGradient(
      colors: const [
        const Color(0xFF3366FF), 
        const Color(0xFF00CCFF),
      ],
      begin: const FractionalOffset(0.0, 0.0),
      end: const FractionalOffset(1.0, 0.0),
      stops: const [0.0, 1.0],
      tileMode: TileMode.clamp
    ),
  ),
);

Здесь, благодаря Color будучи константой, нам удалось получить константу LinearGradient и в конечном итоге постоянная DecoratedBox виджет. Так что не только DecoratedBox создание экземпляра виджета только один раз; но благодаря виджетам, которые являются неизменными; Флаттер распознает, что виджет такой же.

Следствие:

  • Целое поддерево DecoratedBox будет построен один раз.
  • Связанный RenderObject (RenderDecoratedBox в этом случае) не будет обновляться вообще, даже если изменение родительского контейнера

Это объясняется в видео-лекции "Многослойный дизайн Флаттера". Точнее, в 31 мин. Но я бы предложил начать отсюда видео, чтобы лучше понять, что пропущено.

PS: некоторые виджеты не имеют const конструктор вообще. Такие как Container, Но в случае Container Вы могли бы просто использовать DecoratedBox вместо этого, что в основном то, что Container использовать под капотом. Преимущество здесь в том, что DecoratedBox действительно есть конструктор const.

Когда мы используем setState()Flutter вызывает метод сборки и перестраивает каждое дерево виджетов внутри него. Лучший способ избежать этого - использовать const кострукторы.

По возможности используйте константные конструкторы при создании собственных виджетов или при использовании виджетов Flutter. Это помогает Flutter перестраивать только те виджеты, которые нужно обновить.

Итак, если у вас есть StatefulWidget и вы используете setState((){}) чтобы обновить этот виджет, и у вас будут такие виджеты, как:

class _MyWidgetState extends State<MyWidget> {

  String title = "Title";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Column(
        children: <Widget>[
          const Text("Text 1"),
          const Padding(
            padding: const EdgeInsets.all(8.0),
            child: const Text("Another Text widget"),
          ),
          const Text("Text 3"),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          setState(() => title = 'New Title');
        },
      ),
    );
  }
}

Если вы запустите этот код и нажмете кнопку с плавающим действием, все виджеты, определенные как const, не будут восстановлены.

Для получения дополнительной информации: конструкторы const

      import 'package:flutter/material.dart';

class AppColors {
  static const Color kTransparent = Colors.transparent;
  static const Color kWhite = Colors.white;
  static const Color kBlack = Colors.black;
  static const Color kRed = Colors.red;
  static const Color kRedA = Colors.redAccent;
  static const Color kPink = Colors.pink;
  static const Color kPinkA = Colors.pinkAccent;
  static const Color kBlue = Colors.blue;
  static const Color kBlueA = Colors.blueAccent;
  static const Color kLightBlue = Colors.lightBlue;
  static const Color kLightBlueA = Colors.lightBlueAccent;
  static const Color kGreen = Colors.green;
  static const Color kGreenA = Colors.greenAccent;
  static const Color kLightGreen = Colors.lightGreen;
  static const Color kLightGreenA = Colors.lightGreenAccent;
  static const Color kLime = Colors.lime;
  static const Color kLimeA = Colors.limeAccent;
  static const Color kGrey = Colors.grey;
  static const Color kBlueGrey = Colors.blueGrey;
  static const Color kPurple = Colors.purple;
  static const Color kPurpleA = Colors.purpleAccent;
  static const Color kDeepPurple = Colors.deepPurple;
  static const Color kDeepPurpleA = Colors.deepPurpleAccent;
  static const Color kIndigo = Colors.indigo;
  static const Color kIndigoA = Colors.indigoAccent;
  static const Color kYellow = Colors.yellow;
  static const Color kYellowA = Colors.yellowAccent;
  static const Color kOrange = Colors.orange;
  static const Color kOrangeA = Colors.orangeAccent;
  static const Color kDeepOrange = Colors.deepOrange;
  static const Color kDeepOrangeA = Colors.deepOrangeAccent;
  static const Color kAmber = Colors.amber;
  static const Color kAmberA = Colors.amberAccent;
  static const Color kCyan = Colors.cyan;
  static const Color kCyanA = Colors.cyanAccent;
  static const Color kTeal = Colors.teal;
  static const Color kTealA = Colors.tealAccent;
  static const Color kBrown = Colors.brown;
}
Другие вопросы по тегам