Сбор очков знаний Flutter Interview

Android Flutter

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

⚠️系统完整的学习是必须需要的,这里只能帮你总结一些知识点,更多的还请查阅 Dart/Flutter 官网。

Эта статья в основном представляет собой сводку знаний.Если у вас есть какие-либо вопросы, вы можете щелкнуть ссылки каждой статьи для получения подробной информации или обратиться ко мне.Колонка самородков.

Секция дартс

на самом деле узналJavaScriptилиJava/Kotlinлюди, обучениеDartЭто почти не сложно,Дарт сочетает в себе черты динамических и статических языков,Здесь в основном представлены разные или интересные концепции.

  • 1,Dartпринадлежат дастрого типизированный язык, но вы можете использоватьvarобъявить переменные,DartМогусамовыводимый тип данных,varНа самом деле это "синтаксический сахар" времени компиляции.dynamicПредставляет динамический тип, после компиляции, на самом деле являетсяobjectТип, проверка типов не выполняется во время компиляции, но проверка типов выполняется во время выполнения.

  • 2,Dartсерединаifи т.д. заявление поддерживает толькоboolТипы,switchПоддерживается строковый тип.

  • 3.Dartсерединамассив иListэто то же самое.

  • 4.Dartсередина,RunesСимволический текст, это кодированная строка UTF-32, используемая для E.G. Runes input = new Runes('\u{1f596} \u{1f44d}');

  • 5.DartЗамыкания поддерживаются.

  • 6.DartТип номера делится наint и double , без типа float.

  • 7.Dartсерединакаскадный операторВы можете легко настроить логику, следующий код:

event
  ..id = 1
  ..type = ""
  ..actor = "";
  • 8. Оператор присваивания

Более интересными операторами присваивания являются:

AA ?? "999"  ///表示如果 AA 为空,返回999
AA ??= "999" ///表示如果 AA 为空,给 AA 设置成 999
AA ~/999 ///AA 对于 999 整除
  • 9. Дополнительные параметры метода

Dartметод может быть установлензначение параметра по умолчаниюа такжеуказать имя.

Например:getDetail(Sting userName, reposName, {branch = "master"}){}метод, если ветвь не задана, по умолчанию используется "мастер". Тип параметра может быть указан или не указан. Эффект вызова:getRepositoryDetailDao(“aaa", "bbbb", branch: "dev");.

  • 10. Объем

Dartнет ключевых словpublic,privateмодификатор etc,_Нижнее горизонтальное прямое представлениеprivate, но есть@protectedАннотация.

  • 11. Метод строительства

DartНесколько конструкторов в , которые могут быть реализованы именованными методами.

Может быть только один конструктор по умолчанию, иModel.empty()Метод может создать класс с пустыми параметрами, на самом деле имя метода любое, а когда переменная инициализирует значение, нужно только передатьthis.nameВы можете указать его в конструкторе:

class ModelA {
  String name;
  String tag;
  
  //默认构造方法,赋值给name和tag
  ModelA(this.name, this.tag);

  //返回一个空的ModelA
  ModelA.empty();
  
  //返回一个设置了name的ModelA
  ModelA.forName(this.name);
}
  • 12, геттер-сеттер переписать

DartВсе базовые типы, классы и т.д. вObject, значение по умолчаниюNULL, приходит сgetterа такжеsetter, и еслиfinalилиconst, то он имеет только одинgetterметод,ObjectОба поддерживают перезапись геттера и сеттера:

  @override
  Size get preferredSize {
    return Size.fromHeight(kTabHeight + indicatorWeight);
  }
  • 13. Утверждать

assertДействует только в режиме проверки, во время разработки, assert(unicorn == null);Это нормально, только если условие истинно, в противном случае сразу бросается исключение, которое обычно используется в процессе разработки, и в некоторых местах не должно быть никакого государственного суждения.

  • 14. Перепишите оператор, перегрузив его, как показано ниже.operator+/- операции над классом потом.
class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
  
  ···
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}

Операторы, поддерживающие перегрузку:

  • класс, интерфейс, наследование

DartВ классе нет интерфейса, и все классы можно использовать как интерфейсы, при реализации класса как интерфейса нужно использовать толькоimplements, а затем переопределить метод родительского класса.

Dartсредняя поддержкаmixins, в порядке появления должно быть extends,mixins,implements.

  • Zone

Dartпройти вZoneПредставляет среду, в которой выполняется указанный код, аналогично концепции песочницы, вFlutterсерединаC++бегатьDartТакже в_runMainZonedвыполнить в течениеrunZonedметод запускается, и мы также можем передатьZone, для сбора информации, такой как глобальные исключения в среде выполнения:

  runZoned(() {
    runApp(FlutterReduxApp());
  }, onError: (Object obj, StackTrace stack) {
    print(obj);
    print(stack);
  });

При этом вы можете датьrunZonedЗарегистрируйте метод и при необходимости выполните обратный вызов, как показано в следующем коде, чтобы вZoneв любом месте в пределахonDataэтоZoneUnaryCallback, вы можете позвонить вhandleData

///最终需要处理的地方
handleData(result) {
  print("VVVVVVVVVVVVVVVVVVVVVVVVVVV");
  print(result);
}

///返回得到一个 ZoneUnaryCallback 
var onData = Zone.current.registerUnaryCallback<dynamic, int>(handleData);

///执行 ZoneUnaryCallback 返回数据
Zone.current.runUnary(onData, 2);

Асинхронная логика может быть реализована черезscheduleMicrotaskАсинхронные методы выполнения могут быть вставлены:

Zone.current.scheduleMicrotask((){
  //todo something
});

Больше можно найти по адресу:«Полная разработка Flutter и подробное объяснение фактического боя (11, всестороннее и глубокое понимание Stream)»

  • Future

FutureПроще говоря, правильноZoneпакет используется.

НапримерFuture.microtaskв основном реализованоZoneизscheduleMicrotask,а такжеresult._completeПоследний звонок_zone.runUnaryи т.п.

  factory Future.microtask(FutureOr<T> computation()) {
    _Future<T> result = new _Future<T>();
    scheduleMicrotask(() {
      try {
        result._complete(computation());
      } catch (e, s) {
        _completeWithErrorCallback(result, e, s);
      }
    });
    return result;
  }

Dartпройти вasync/awaitилиFutureопределяют асинхронные операции, а на самом делеasync/awaitЭто также просто синтаксический сахар, который в конечном итоге преобразуется компилятором вFuture.

Интересно посмотреть здесь:

generators

code_generator.dart

Подробное объяснение полного развития Flutter и реального боя (11. Всестороннее и глубокое понимание Stream)

  • Stream

Streamда даZoneИспользуется другой пакет.

Еще одна асинхронная операция в Dart,async* / yieldилиStreamподдающийся определениюStreamасинхронный,async* / yieldЭто также просто синтаксический сахар, который в конечном итоге преобразуется компилятором вStream. Stream также поддерживает синхронные операции.

1),Streamв основном включаютStream,StreamController,StreamSinkа такжеStreamSubscriptionЧетыре ключевых объекта можно приблизительно резюмировать следующим образом:

  • StreamController: как следует из названия класса, для всегоStreamУправление процессом, предоставляющее различные интерфейсы для создания различных потоков событий.

  • StreamSink: обычно используется в качестве входа на мероприятие, обеспечивая, например,add,addStreamЖдать.

  • Stream: сам источник событий, который обычно можно использовать для мониторинга событий или преобразования событий, напримерlisten,where.

  • StreamSubscription: объект после подписки на событие, который якобы используется для управления различными операциями, такими как подписка, напримерcacenl,pause, и в то же время это также ключ к транзиту событий внутри.

2),обычно проходятStreamControllerСоздайтеStream;пройти черезStreamSinkдобавить событие; передатьStreamслушать события; проходитьStreamSubscriptionУправление подписками.

3),Streamподдерживает различные изменения, такие какmap,expand,where,takeи другие операции, поддерживая преобразование вFuture.

Больше можно найти по адресу:«Полная разработка Flutter и подробное объяснение фактического боя (11, всестороннее и глубокое понимание Stream)»

Флаттер раздел

Основное различие между Flutter и React Native заключается в том, чтоПользовательский интерфейс Flutter рендерится напрямую с помощью skia, а React Native преобразует элементы управления в js в собственные элементы управления и отображает их нативно., для получения дополнительной информации см.:"Углубленный анализ мобильной кроссплатформенной разработки".

  • существует во флаттереWidget,Element,RenderObject,Layerчетыре дерева, из которыхWidgetа такжеElementэто отношение один ко многим,

  • Elementпроводится вWidgetа такжеRenderObject, а такжеElementа такжеRenderObjectявляется взаимно-однозначным соответствием (исключаяElementне существуетRenderObjectситуация, напримерComponentElementне доступенRenderObject),

  • когдаRenderObjectизisRepaintBoundaryдляtrue, то области образуютLayer,такне каждыйRenderObjectкак естьLayer, потому что этоisRepaintBoundaryВлияние.

Подробнее о«Полная разработка Flutter и подробное объяснение фактического боя (девять, принцип подробного рисования)»

  • Во трепетеWidgetНеизменный, остается один кадр за раз, еслиизменение происходит черезStateРеализуйте кросс-фреймовое хранилище,а такжеЧто на самом деле делает макет и рисунок массиваRenderObject, Elementдействовать как мост между ними,Stateхранится вElementсередина.

  • во флаттереBuildContextтолько интерфейс, аElementпонял это.

  • Во трепетеsetStateНа самом деле называетсяmarkNeedsBuild, внутри методаотметить этоElement дляDirty, то на следующем кадреWidgetsBinding.drawFrameбудет нарисовано, что видноsetStateНе действует сразу.

  • Во трепетеRenderObjectсуществуетattch/layoutпройдет позжеmarkNeedsPaint();Процесс перерисовки страницы примерно следующий:

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

  • нормальные обстоятельстваRenderObject Последовательность вызова метода, связанного с компоновкой:layout -> performResize -> performLayout -> markNeedsPaint ,Однако пользователи обычно не вызывают напрямуюlayout, нопройти черезmarkNeedsLayout, конкретный процесс выглядит следующим образом:

  • Генерал во флаттереjsonданные изStringПеревести вObjectпроцесс должен пройти сначалаMapТипы.

  • Во трепетеInheritedWidgetобычно используется длясовместное использование состояния,Такие какTheme,Localizations,MediaQueryи т. д., все это для достижения общего состояния, чтобы мы могли передатьcontextЧтобы получить общее состояние, напримерThemeData theme = Theme.of(context);

существуетElementизinheritFromWidgetOfExactTypeВ реализации метода естьMap<Type, InheritedElement> _inheritedWidgetsОбъект.

_inheritedWidgetsОбычно пустой, только если родительский элемент управленияInheritedWidgetили самInheritedWidgetsбудет инициализирован, когда родительский элемент управленияInheritedWidgetкогда этоMapОн будет передаваться и объединяться уровень за уровнем.

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

  • По умолчанию во Flutter в основном черезruntimeTypeа такжеkeyОбновление приговора:
static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
  }
}

Жизненный цикл во Flutter

  • initState()Указывает текущийStateбудет иBuildContextсвязаны, но в настоящее времяBuildContextНе полностью загружен, если вам нужно попасть в этот методBuildContext,Могуnew Future.delayed(const Duration(seconds: 0, (){//context});один раз.

Точнее, его теперь следует использоватьSchedulerBinding

  • didChangeDependencies()существуетinitState()после звонка, когдаStateЭтот метод вызывается при изменении зависимостей объекта, а также при его инициализации.

  • deactivate()когдаStateЭтот метод вызывается при временном удалении из дерева просмотра, а также вызывается при переключении страницы. (исчезла в новой версии)

  • dispose()Виджет уничтожается, перед вызовом этого метода всегда вызывается функция deactivate().

  • didUpdateWidgeкогдаwidgetВызывается при изменении состояния.


  • пройти черезStreamBuilderа такжеFutureBuilderмы можем быстро использоватьStreamа такжеFutureБыстро создайте наш асинхронный элемент управления:«Полная разработка Flutter и подробное объяснение фактического боя (11, всестороннее и глубокое понимание Stream)»

  • Во трепетеrunAppНачальная запись на самом деле являетсяWidgetsFlutterBinding, в основном черезBindingBaseподклассGestureBinding,ServicesBinding,SchedulerBinding,PaintingBinding,SemanticsBinding,RendererBinding,WidgetsBindingподожди, черезmixinsкомбинация .

  • Нити дротика во FlutterЦикл событий и очередь сообщенийсуществует в виде двух очередей задач,Одна — внутренняя очередь микрозадачи, другая — внешняя очередь события, причем приоритет микрозадачи выше, чем событие.

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

  • существует во флаттереЧетыре потока соответственноUI Runner,GPU Runner,IO Runner,Platform Runner(родной основной поток), а во Flutter можно пройтиisolateилиcomputeВыполнение настоящих асинхронных операций между потоками.

PlatformView

Прошел во флаттереPlatformViewможет быть вложенным изначальноViewприбытьFlutterВ пользовательском интерфейсе это фактически используетсяPresentation + VirtualDisplay + SurfaceИ так далее, общий принцип:

Используя технологию, аналогичную отображению вторичного экрана,VirtualDisplayкласс представляет виртуальный дисплей, вызовDisplayManagerизcreateVirtualDisplay()метод, который отображает содержимое виртуального дисплея вSurfaceконтроль, а потомSurfaceИдентификатор сообщается Dart, поэтому, когда движок рисует, он находит соответствующий идентификатор в памяти.SurfaceЗатем рисуются данные памяти экрана. Эм...Технология отображения рендеринга скриншотов управления в реальном времени.


  • Режим отладки Flutter — это режим JIT, а режим выпуска — режим AOT.

  • Во Flutter вы можете пройтиmixins AutomaticKeepAliveClientMixin, затем перепишитеwantKeepAliveДержите страницу, не забывайте быть на удерживаемой страницеbuildвызыватьsuper.build. (Потому что характеристики миксинов).

  • События жестов флаттера в основном оцениваются по соревнованиям:

ЕстьhitTestВсе элементы управления, которые необходимо обработать, соответствуютRenderObject, отchildприбытьparentВсе они объединены в список, добавленный от самого внутреннего к самому внешнему.

Затем запустите выполнение цикла for из дочернего элемента в начале очереди.handleEvent метод, выполнитьhandleEventПроцесс не будет прерван перехватом.

При обычных обстоятельствах событие Down не определяет победителя.В большинстве случаев победитель определяется, когда происходит событие MOVE или UP.

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

ТакжеdidExceedDeadlineОбрабатывать событие Down при нажатии и удерживать дополнительную обработку, в то время как обработка жестов обычно включенаGestureRecognizerподкласс.

Для получения более подробной информации, пожалуйста, проверьте:«Полная разработка флаттера и подробное объяснение фактического боя (тринадцать, всестороннее подробное касание и принцип скольжения)»

Platform Channel

Во Flutter вы можете пройтиPlatform ChannelПозвольте коду Dart взаимодействовать с собственным кодом:

  • BasicMessageChannel: Используется для передачи строк и полуструктурированной информации.
  • MethodChannel: Используется для передачи вызова метода.
  • EventChannel: для связи с потоками событий.

в то же времяPlatform Channelне потокобезопасный, для получения более подробной информации см. Xianyu Technology"Глубокое понимание канала платформы Flutter"

Базовые типы данных отображаются следующим образом:


Заставка Android

в AndroidFlutterПо умолчанию он начинается сFlutterActivityDelegate.java Читать внутри AndroidManifset.xmlmeta-dataярлык, которыйio.flutter.app.android.SplashScreenUntilFirstFrameЕсли бит флага равен true, запустится эффект экрана-заставки (аналогично стартовой странице IOS).

Собственный код будет читаться при запускеandroid.R.attr.windowBackgroundуточнитьDrawable, используемый для отображения эффекта заставки, а затем передатьflutterView.addFirstFrameListener,существуетonFirstFrameУдалить заставку в .

Ну это все пока здесь, если будут какие-то проблемы, то это будет исправлено или дополнено, а я добавлю позже.

Рекомендация ресурса

Полные проекты с открытым исходным кодом рекомендуется: