Flutter中的BuildContext

質數心情發表於2021-03-05

Flutter中經常可以看到Widget build(BuildContext context) {}, Theme.of(context)這些需要傳遞BuildContext的場景.


abstract class BuildContext {
  /// The current configuration of the [Element] that is this [BuildContext].
  Widget get widget;

  /// The [BuildOwner] for this context. The [BuildOwner] is in charge of
  /// managing the rendering pipeline for this context.
  BuildOwner? get owner;
}

複製程式碼

BuildContext是一個抽象類.


@override
StatelessElement createElement() {
    // TODO: implement createElement
    return super.createElement();
}

複製程式碼

Widget在構建的時候build會呼叫createElement.螢幕上顯示的檢視樹其實就是ElementTree. widgetTree負責配置資訊,ElementTree負責顯示資訊,RenderObject負責渲染樹

abstract class StatelessWidget extends Widget {
  const StatelessWidget({ Key? key }) : super(key: key);
  @override
  StatelessElement createElement() => StatelessElement(this);
  @protected
  Widget build(BuildContext context);
}
複製程式碼

createElement呼叫StatelessElement(StatelessWidget widget),this就是widget.


/// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement {
  /// Creates an element that uses the given widget as its configuration.
  StatelessElement(StatelessWidget widget) : super(widget);

  @override
  StatelessWidget get widget => super.widget as StatelessWidget;

  @override
  Widget build() => widget.build(this);

  @override
  void update(StatelessWidget newWidget) {
    super.update(newWidget);
    assert(widget == newWidget);
    _dirty = true;
    rebuild();
  }
}

複製程式碼

build()呼叫了widget.build(this),this是StatelessElement.

所以在widget進入檢視樹的時候,widget會傳給Element引用,Element通過widget呼叫widget的build(BuildContext context),傳入的context就是Element.

BuildContext = Element.BuildContext物件實際上就是Element物件.

of(context)方法


Theme.of(context).backgroundColor
Navigator.of(context).push

複製程式碼

在Flutter中經常會這樣操作,of(context)是Flutter開發的一種約定,從當前傳入的context向上遍歷尋找符合的state,是對跨元件獲取資料的一種封裝.


// Theme.of(context)

static ThemeData of(BuildContext context) {
    final _InheritedTheme? inheritedTheme = context.dependOnInheritedWidgetOfExactType<_InheritedTheme>();
    final MaterialLocalizations? localizations = Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
    final ScriptCategory category = localizations?.scriptCategory ?? ScriptCategory.englishLike;
    final ThemeData theme = inheritedTheme?.theme.data ?? _kFallbackTheme;
    return ThemeData.localize(theme, theme.typography.geometryThemeFor(category));
  }
複製程式碼

相關文章