«Финиш» Флаттер с наиболее удобной позицией лежа на переднем конце

Flutter
«Финиш» Флаттер с наиболее удобной позицией лежа на переднем конце

Автор|Чжу Янь (И Шэн)

Редактор | Orange Jun

Произведено | Alibaba New Retail Tao Technology

Самая горячая кросс-энд технология на данный момент принадлежит Flutter, и никто не должен сомневаться в этом. Самая очевидная черта новой технологической тенденции заключается в том, что она должна хотеть убить «переднюю волну» на берегу. Эта передняя волна — это «React Native», «weex». В настоящее время, если вы ищете «Flutter reactNative» в поисковой системе, это все сравнение и оценка этих двух технологий.

предисловие

Один за другим: «Перерыв», если не согласны! ! ! вкус.

Да, если вы скучаете по технологиям React Native и Weex, чтобы «взорвать» интерфейс, вы не можете пропустить Flutter, В наши дни вы не знаете кросс-энд технологии, так как вы можете стесняться говорить что вы [front-end].

В мае 2020 года команда Flutter представила первую стабильную версию Flutter 1.17.x.

Официально новый выпуск закрывает 6 339 проблем с Flutter 1.12, объединяет 3 164 PR от 231 участника и исправляет множество ошибок. Помимо улучшений качества, в новой версии также добавлены некоторые новые функции:

  • Улучшения мобильной производительности и размера пакета приложений

Работает на 20-37% быстрее, анимация iOS снижает загрузку ЦП/ГП на 40%; пример Flutter Gallery, размер пакета уменьшен на 18,5%, а память уменьшена на 70% при быстрой прокрутке больших изображений.

  • Metal повышает производительность iOS на 50%

Разработчики могут использовать металлическую API для непосредственного доступа к базовым графическим процессорам. На IOS-устройствах трепетание будет использовать металл по умолчанию, изготовление приложений в большинстве случаев, в большинстве случаев прилагаясь при увеличении скорости рендеров около 50%.

  • Виджет нового материала

Это новый компонент виджета NavigationRail, разработанный и реализованный командой Google Material Design. NavigationRail отлично подходит для приложений, которые переключаются между мобильным и настольным компьютером. Также была добавлена ​​новая библиотека анимаций, предоставляющая готовые анимации, реализующие новую спецификацию движения материала.

  • Dart DevTools for Flutter

Это артефакт, и вы должны быть знакомы с chrome DevTools, Dart DevTools — это инструмент для отладки кода Dart и Flutter и анализа производительности. Этот набор инструментов очень функционален, включая производительность, пользовательский интерфейс, горячее обновление, горячую перезагрузку, журнал регистрации и многие другие функции. (Этот инструмент будет представлен в специальном выпуске позже).

  • Новая текстовая тема Flutter и шрифты Google

В новом выпуске команда Flutter завершила реализацию Type Scale, спецификации дизайна материалов 2018 года, не нарушая существующие приложения Flutter. То есть API TextTheme совместим с предыдущими версиями и предупреждает только о старых устаревших именах. В то же время новую тему также можно сопоставить с новым шрифтом Google Fonts for Flutter v1.0.

  • Доступность и интернационализация

Более комплексная работа, исправления прокрутки, текстового поля и других виджетов ввода. GitHub имеет полный список безбарьерных функций в этом выпуске. С точки зрения интернационализации, ошибка метода ввода с клавиатуры Samsung была завершена.

  • Другие важные изменения

При использовании pushReplacement сохраните предыдущий путь и продолжите анимацию Устаревший UpdateLiveRegionEvent Задержка декодирования изображения при прокрутке на высокой скорости Ошибка переполнения выделения текста (Android) Параметры подсказки кэша утверждений для пустых объектов чертежа кеш изображений в реальном времени В пределах видимого диапазона убедитесь, что выбор расчета высоты вспомогательного блока точен. Сгенерировать запрос сообщения в gen_l10n Удалить isinitialroute из RouteSettings Переместите mouse_tracking.dart в рендеринг

Для получения подробной информации, пожалуйста, обратитесь к официальному адресу:medium.com/flutter/Appendix…

В каждой итерации есть небольшие интересные улучшения, но для студентов веб-интерфейса, которые плохо знакомы с Flutter...

Ну и вернемся к заголовку, автор, как традиционный веб-фронтендер, хочет "лежать" и изучать Flutter с наиболее привычной точки зрения фронтенда. Не восхищайтесь им, просто посмотрите на него! ! ! Начните с интереса.

текст

На самом деле существует множество ресурсов, на которые можно ссылаться при создании среды Flutter. Не буду здесь вдаваться в подробности (знаю, что ям много, и в последующих статьях имею возможность обобщить ямки, с которыми столкнулся).

Если вам интересно, вы можете обратиться к "Создание среды установки Flutter" (flutter.talents/docs/индивидуальное тело...), я предлагаю всем здесь, вы должны сами настроить окружение, запустить официальную демку и пересечь реку на пони.

При наличии среды Редактор конфигурации (flutter.talents/docs/индивидуальное тело...

Затем «создайте проект Flutter» (flutter.talents/docs/индивидуальное тело...

После того, как проект создан, вы можете сначала запустить его с помощью флаттера.

flutter doctor // 让 flutter 医生检查一下环境和配置,得到四个 ☑ 后,恭喜你通过考核。
flutter run // 奔跑吧...

Хорошо, давайте запустим, вы увидите официальный пример подсчета, нажмите на изображение с плюсом, чтобы выполнить операцию сложения.

В это время мы видим, что в каталоге проекта есть файл входа с именем main.dart. Затем откройте main.dart следующим образом:

(Почему вы видите, что код длиннее моего, потому что я загнулся!!!) Дело не в этом, дело в том, что каждый класс наследует символ с суффиксом Widget.

Умный, вы почувствуете, что виджет и флаттер имеют какую-то таинственную связь.

«Бинго!» Да, у Флаттера есть два тяжелых оружия, одно называется Дротик, а другое — Виджет.

Все в Dart происходит от Object, а все компоненты во Flutter — от Widget.

Что касается мощного Дротика, я не буду говорить о нем сегодня, о Дротике будет время поговорить в отдельной главе позже.

Во-первых, представлена ​​старая схема архитектуры Flutter.

В мире Flutter концепции, включая представления, контроллеры представлений, макеты и т. д., строятся поверх виджетов.

Виджет — это абстрактное описание компонента Flutter. Таким образом, основа освоения Flutter — научиться использовать виджет для начала.

Процесс рендеринга интерфейса Flutter делится на три этапа: верстка, отрисовка и композиция.Верстка и отрисовка завершаются во Flutter framework, а композиция передается движку:

Flutter Комбинируя вложенные друг в друга элементы управления, можно построить интерфейс любой функции произвольной сложности.

  • Наиболее важные классы, которые он содержит:
class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding,PaintingBinding, RendererBinding, WidgetsBinding { ... }

abstract class Widget extends DiagnosticableTree { ... }
abstract class StatelessWidget extends Widget { ... }
abstract class StatefulWidget extends Widget { ... }
abstract class RenderObjectWidget extends Widget { ... }
abstract class Element extends DiagnosticableTree implements BuildContext { ... }
abstract class RenderObjectElement extends Element { ... }

class StatelessElement extends ComponentElement { ... }
class StatefulElement extends ComponentElement { ... }

Основные функции вышеперечисленных классов следующие:

Все программы, разработанные на основе системы управления Flutter, должны использовать WidgetsFlutterBinding, который является управляющей структурой Flutter и связующим слоем движка Flutter.

Виджет — это базовый класс всех элементов управления, и все его свойства доступны только для чтения.

Все классы реализации RenderObjectWidget отвечают за предоставление информации о конфигурации и создание конкретных элементов RenderObjectElements.

Элемент — это средний слой, который Flutter использует для разделения дерева элементов управления и реального объекта рендеринга. Элемент управления используется для описания соответствующего свойства элемента. После перестроения элемента управления один и тот же элемент можно использовать повторно.

RenderObjectElement содержит объекты RenderObject, которые фактически отвечают за компоновку, отрисовку и проверку попадания.

StatelessWidget и StatefulWidget напрямую не влияют на создание RenderObject, они отвечают только за создание соответствующего RenderObjectWidget.

StatelessElement и StatefulElement также являются похожими функциями.

Это очень сложно, не так ли? Пока не беспокойтесь об этом. Простое выражение Widget выглядит так:

Виджет = стиль (css) + семантика разметки (теги) + компонентизация (официальная) + привязка данных (реквизит)

"Что? Разве это не просто реакция?"

Да, концепция React похожа на виджет Flutter.

«Поскольку существует концепция реагирования, существует ли еще состояние, setState?»

И да, во Flutter действительно есть концепция, похожая на механизм состояния состояния, и у него есть метод setState.

«В куполе есть два базовых класса, для чего нужны StatelessWidget и StatefulWidget?»

StatelessWidget и StatefulWidget, эти два класса особенно важны, почти все компоненты создаются на их основе.

StatelessWidget — это виджет, состояние которого неизменяемо, называемый виджетом без состояния. После того, как начальное состояние установлено, его нельзя изменить. При необходимости создайте заново.

StatefulWidget может сохранять свое собственное состояние и называется виджетом с отслеживанием состояния. Сначала Flutter сохраняет состояние, созданное во время инициализации, которое позволяет перестроить дерево виджетов, изменив состояние для внесения изменений в пользовательский интерфейс. Способ изменения состояния — это наиболее часто используемый артефакт setState, и простое изменение данных не приведет к изменению пользовательского интерфейса Эта концепция аналогична нашему React.

Если вы новичок во Flutter, вам не нужно запоминать так много базовых классов компонентов, достаточно запомнить следующую формулу.Не будет преувеличением сказать, что вы сможете разработать проект Flutter, если знакомы с этой формулой:

демонтаж

Ориентируясь на состав виджетов, разберем и проанализируем, отметим семантику, стиль и компонентность.

семантика разметки

Почему это называется не «шаблон», «метка», «элемент», а называется «семантика разметки», ведь структура виджета флаттера — это не просто «шаблон», «метка», «элемент». Структура описания виджета больше похожа на стадию виртуального дома React, которая сжимает соответствующий контекст и отображает его в объектно-ориентированной структуре.

Давайте сначала посмотрим на структуру виртуального дома (псевдокод), созданную React:

var newTree = el('div', {'id': 'container'}, [
    el('h1', {style: 'color: red'}, ['simple virtal dom']),
    el('p', ['Hello, virtual-dom']),
    el('ul', [el('li'), el('li')])
])

Давайте посмотрим на структуру кода виджета, созданную флаттером с помощью Dart:

Widget build(BuildContext context) {
    return new Column(
      children: <Widget>[
        new Container(
          padding: new EdgeInsets.only(top:100.0),
          child: new Text('这是一个组件')
        ),
        new Container(
          decoration: new BoxDecoration(border: new Border.all(width:1.0,color: Colors.blue)),
          padding: new EdgeInsets.all(20.0),
          child: new Text('来自输入框:'+active)
        )
      ],
    );
  }

Разве это не намного более знакомо.

Примечание: Многие разработчики интерфейса не привыкли к такому способу написания.В настоящее время некоторые разработчики продвигают в сообществе использование тегов jsx перед компиляцией, а затем анализируют их в дереве тегов после компиляции, например, это предложение по дизайну DSX. .

Хотя jsx->tag tree — это всего лишь предложение, на самом деле оно может помочь нам понять его.Стиль, который это предложение хочет выразить, выглядит следующим образом:

class MyScaffold extends StatelessWidget {
  build(context) {
    return <Material>
      <Column>
          <MyAppBar
             title={<Text 
               text='Example title'
               style={Theme.of(context).primaryTextTheme.title},
             />}
          />
          <Expanded>
            <Center>
              <Text text='Hello, world!'/>
            </Center>
          </Expanded>
      </Column>
    </Material>;
  }
}

Как бы выглядел вышеприведенный jsx, если бы он был написан на Dart? следующим образом:

class MyScaffold extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Column(
        children: <Widget>[
          MyAppBar(
            title: Text(
              'Example title',
               style: Theme.of(context).primaryTextTheme.title,
            ), // Text
          ), // MyAppBar
          Expanded(
            child: Center(
              child: Text('Hello, world!'),
            ), // Center
          ), // Expanded
        ], // <Widget>[]
      ), // Column
    ); // Material
  }
}

Хотя аналогия между Flutter и React несколько надуманная, я могу лично обобщить некоторые методы для простоты понимания:

  • Имена классов с заглавной буквы эквивалентны именам тегов jsx.

  • дочерний эквивалентен дочернему тегу + макет jsx

  • Children эквивалентен вложенному тегу группы jsx (отличному от дочернего)

  • Другие свойства эквивалентны свойствам jsx.

  • Вы заметили, что второй абзац синтаксиса dart будет помечен символом комментария "//". Он автоматически добавляется редактором IDE после идентификации проекта Flutter. Как и в языке jsx, метка закрыта, чтобы облегчить обнаружение начало метки.начальный узел.

стиль

Для понимания стиля Flutter вы можете проверить этот официальный документ, который также использует аналогию, чтобы интуитивно понять взаимосвязь между HTML, стилем CSS и флаттером.

флаттер ест тот.клуб/веб-аналоги…

Автор выбирает ключевые части примеров и сравнивает их для иллюстрации (из-за нехватки места структура css отношений родитель-потомок представлена ​​вкладками):

Стиль текста:



.demo1 {
      background-color: #e0e0e0;
      width: 320px;
      height: 240px;
      font: 900 24px Georgia;
      letter-spacing: 4px; 
      text-transform: uppercase; 
    }


var demo1 = new Container( 
  child: new Text(
    "Lorem ipsum".toUpperCase(), // 对应 左边的文本转换大小写
    style: new TextStyle( // 对应 左边的 font
      fontSize: 24.0
      fontWeight: FontWeight.w900,
      fontFamily: "Georgia",
      letterSpacing: 4.0, 
    ),
  ),
  width: 320.0,  // 对应 左边的 width
  height: 240.0,  // 对应 左边的 height
  color: Colors.grey[300],  // 对应 左边的 background-color
);

Центрировать стиль:



.demo2 {
      display: flex;
      align-items: center;
      justify-content: center; 
    }


var demo2 = new Container(
  child:  new Center( // 对应左边的整个 flex 属性
    child:  new Text("Lorem ipsum")
   )
  );
);

Установите максимальную (маленькую) ширину:



  .container{
   width:300px
   .demo3 {
      width: 100%;
      max-width: 240px; 
   }
  }


// 对于嵌套容器,如果父级的宽度小于子级宽度,则子级容器将自行调整大小以匹配父级。
var container = new Container(
   child: new Center(
        child: new Text("Lorem ipsum"),
        decoration: new BoxDecoration( ... ), // constraints属性,创建一个新的BoxConstraints来设置minWidth或maxWidth
        width: 240.0, // 对应左边的 max-width
    ),
   width:300.0
  ),

Поворотные компоненты:


   
 .redbox {
       transform: rotate(15deg); 
 }


var container = new Container( // gray box
    child:  new Transform( // 对应左边的 transform
      child:  new Container(  ... ),
      alignment: Alignment.center, // 对应左边的 transform
      transform: new Matrix4.identity() // 对应左边的 transform
        ..rotateZ(15 * 3.1415927 / 180),
    ), 
  )
);

Масштабный компонент:


   
.redbox {
  transform: scale(1.5); 
}

var container = new Container( // gray box
    child:  new Transform( // 对应左边的 transform
      child:  new Container(  ... ),
      alignment: Alignment.center, // 对应左边的 transform的中心
      transform: new Matrix4.identity() // 对应左边的 transform
        ..scale(1.5),
    ), 
  )
);

Установите абсолютные и относительные позиции:


   
.greybox {
     position: relative; 
     .redbox {
       position: absolute;
       top: 24px;
       left: 24px; 
     }
}
var container = new Container( // grey box
  child: new Stack( // 相对跟容器位置 relative
    children: [
      new Positioned( // 相对父容器位置 absolute
        child:  new Container( ... ),
        left: 24.0,
        top: 24.0,
      )],
  )
);

Цветовой градиент:


.redbox {
  background: linear-gradient(180deg, #ef5350, rgba(0, 0, 0, 0) 80%); 
}

var container = new Container( // grey box
  child: new Center(
    child: new Container( // red box
      child: new Text( ... ),
      decoration: new BoxDecoration( 
        gradient: new LinearGradient( // 对应左边的 background: linear-gradient
          begin: const Alignment(0.0, -1.0),
          end: const Alignment(0.0, 0.6),
          colors: [
            const Color(0xffef5350),
            const Color(0x00ef5350)
          ],
        ),
      )
    ),
  )
);

Филе:



.redbox {
  border-radius: 8px; 
}
var container = new Container( // grey box
  child: new Center(
    child: new Container( // red circle
      child: new Text( ... ),
      decoration: new BoxDecoration(
        borderRadius: new BorderRadius.all(
          const Radius.circular(8.0),
        ), 
      )
    ),
  )
);

тень:



.redbox {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.8),
              0 6px 20px rgba(0, 0, 0, 0.5);
}


var container = new Container( // grey box
  child: new Center(
    child: new Container( // red box
      child: new Text( ... ),
      decoration: new BoxDecoration(
        boxShadow: [ // 对应左边的  box-shadow
          new BoxShadow (
            color: const Color(0xcc000000),
            offset: new Offset(0.0, 2.0),
            blurRadius: 4.0,
          ),
          new BoxShadow (
            color: const Color(0x80000000),
            offset: new Offset(0.0, 6.0),
            blurRadius: 20.0,
          ),
        ], 
      )
    ),
  )
);

Чтобы нарисовать круг:



.redcircle {
  text-align: center;
  width: 160px;
  height: 160px;
  border-radius: 50%; 
}

var container = new Container( // grey box
  child: new Center(
    child: new Container( // red circle
      child: new Text( ... ),
      decoration: new BoxDecoration(
        color: Colors.red[400],
        shape: BoxShape.circle, // 画圆和圆角不太一样,用的是BoxShape绘制图像能力
      ),
      width: 160.0,
      height: 160.0, 
    ),
  )
);

Встроенные стили:



// css 的内联结构
.greybox {
    font: 900 24px Roboto; 
   .redbox {
       em {
          font: 300 48px Roboto;
          font-style: italic;
      }
    } 
}
var container = new Container( // grey box
  child: new Center(
    child: new Container( // red box
      child:  new RichText(
        text: new TextSpan(
          style: bold24Roboto,
          children: [
            new TextSpan(text: "Lorem "), // 继承内联样式
            new TextSpan(
              text: "ipsum",
              style: new TextStyle( // 具有自定义样式的单独样式
                fontWeight: FontWeight.w300,
                fontStyle: FontStyle.italic,
                fontSize: 48.0,
              ),
            ),
          ],
        ),
      ),
    ),
  )
);

составной

Официальный каталог виджетов

После клика на каждой карточке в ней появляются подкарточки.С расширенной широты это выглядит так:

Это действительно огромная компонентная система, это не предоставляется сообществом, это официально.

Команда Flutter тщательно реализовала методы и типы компонентов, которые сегодня можно увидеть на рынке. Лично я считаю, что в этом есть как плюсы, так и минусы.

Недостатки в первую очередь:

1. Стоимость обучения увеличивается, а кривая все еще остается относительно крутой.

2. Путь прямого наследования компонентов беспорядочный, например Унаследованными от Widget являются следующие основные классы, которые также очевидны: PreferredSizeWidget ProxyWidget RenderObjectWidget StatefulWidget StatelessWidget. Однако подклассы StatelessWidget и StatefulWidget слишком параллельны, с неясными именами, без абстрактных архитектурных, иерархических или башенных уровней.

Виджет без состояния:

StatefulWidget

3. Определение пользовательских компонентов неоднозначно.При такой огромной библиотеке компонентов существует более систематическая библиотека сторонних компонентов, чтобы заменить ее в будущем, или Flutter официально не рекомендует использовать сторонние компоненты.Это неубедительно. .

А потом плюсы:

1. Это может предотвратить залив колес в будущем.Когда команда находится в тупике по поводу того, какую библиотеку колес использовать, лучшая причина - слово «официальный», потому что использование официального может ослабить и избежать некоторых проблем, таких как как: итерации версий не синхронизированы, узкие места в производительности, несогласованные спецификации также могут быстро поддерживать официальные вспомогательные инструменты.

2. Именно потому, что официальный стандарт является унифицированным, что обеспечивает удобство автоматизированной компиляции, автоматизированного построения, настройки тестов, визуализации и даже обеспечивает поддержку бизнес-сценариев моделирования внешнего интерфейса AI.Говорят, что внешние компоненты похожи на Lego, а Flutter — частица стандарта унифицированного LEGO.

3. Веяние мира, если он давно разделен, то он должен быть объединен, а если он надолго объединен, он должен быть разделен.

Внешний интерфейс пережил эпоху мультимедийных унифицированных флэш-страниц для ПК, но позже был разрушен Джобсом и H5;

После этого было процветание H5 и хаос фреймворка, грамматики и режима построения;

Потом под голос "не обновляй, не могу научиться" надеюсь, что будет кроссплатформенная система, объединяющая реки и озёра;

Позвольте разработчикам больше сосредоточиться, улучшить бизнес-контент и создать «новую, классную и ослепительную» презентационную ситуацию.

Возможно, здесь действительно рождается король фронтовых рек и озер.

наконец

Реальный виджет Flutter намного сложнее.Среди блестящих компонентов виджета автор хочет использовать часть моего собственного понимания, чтобы извлечь суть, чтобы постепенно понять нового парня Flutter.Есть места, где понимание не в место, и вы можете поправить меня. Команда авторов также разрабатывает набор приложений «Flutter Rookie Handbook», чтобы помочь вам ознакомиться со сложным виджетом Flutter.

Оригинальная ссылка (GitHub.com/Naked730/за…

Добро пожаловать в группу QQ Flutter Go для друзей, которые изучают Flutter: 679476515.

Адрес проекта «Flutter Go»alibaba/flutter-goИли нажмите, чтобы прочитать исходный текст