Flutter BuildContext 探究

小德_REN發表於2019-01-18

0x00 前言

BuildContext是Flutter的重要部分,但是目前網上講BuildContext的文章太少了,所以本篇文章講講BuildContext

0x01 BuildContext 介紹

BuildContext,顧名思義,Build(構建Widget) Context(應用上下文),就是構建Widget中的應用上下文。

所以BuildContext只出現在兩個地方:

  1. StatelessWidget.build 方法中:建立StatelessWidget的build方法
  2. State物件中:一個是建立StatefulWidget的State物件的build方法中,另一個是State的成員變數

BuildContext實際是Element,BuildContext是為了阻止直接對Element操作而抽象出來的,所以BuildContextElement的抽象類,所有Element都繼承自BuildContext

每一個Widget都有一個BuildContext

BuildContext是Widget在Widget樹中位置的控制程式碼。

0x02 訪問 BuildContext 例項物件

BuildContextWidgetBulder(例如:StatelessWidget.build, State.build)方法傳遞;

BuildContext也是State的成員變數,在State內部,可以通過context直接訪問

0x03 BuildContext 使用

BuildContext的作用主要是通過上下文獲取指定的資料;

例如:Theme.of(context) 或者 showDialog(context: context,....)都需要BuildContext作為引數,這裡的BuildContext就是呼叫這些方法的Widget的代表。

0x05 BuildContext 注意事項

每一個Widget都有一個BuildContext。假設有個A Widget,A Widget裡肯定會有StatelessWidget.build或者State.build的build方法,build方法建立了 B Widget並返回,A Widget就是B Widget的父Widget,相應的, A Widget的BuildContext也是是B Widget 的BuildContext的父節點。

下面給一個例子加深理解:

@override
  Widget build(BuildContext context) {
    // here, Scaffold.of(context) returns null,
    //在Scaffold建立之前,如果在這裡呼叫Scaffold.of(context)會返回null,是因為此時Scaffo//ld還沒建立,所以其BuildContext也沒有建立,為了在建立Scaffold的時候就取到他的BuildC//ontext,要使用Builder
    return Scaffold(
      appBar: AppBar(title: Text('Demo')),
      body: Builder(
        builder: (BuildContext context) {
          return FlatButton(
            child: Text('BUTTON'),
            onPressed: () {
              // here, Scaffold.of(context) returns the locally created Scaffold
              Scaffold.of(context).showSnackBar(SnackBar(
                content: Text('Hello.')
              ));
            }
          );
        }
      )
    );
  }
複製程式碼

0x04 BuildContext 內部方法解析

為什麼BuildContext可以用來獲取上下文的資料,主要是因為BuildContext具有的以下方法:

  1. ancestorInheritedElementForWidgetOfExactType(Type targetType) → InheritedElement
Obtains the element corresponding to the nearest widget of the given type, which must be the type of a concrete InheritedWidget subclass. [...]
複製程式碼
  1. ancestorRenderObjectOfType(TypeMatcher matcher) → RenderObject
Returns the RenderObject object of the nearest ancestor RenderObjectWidget widget that matches the given TypeMatcher. [...]
複製程式碼
  1. ancestorStateOfType(TypeMatcher matcher) → State
Returns the State object of the nearest ancestor StatefulWidget widget that matches the given TypeMatcher. [...]
複製程式碼
  1. ancestorWidgetOfExactType(Type targetType) → Widget
Returns the nearest ancestor widget of the given type, which must be the type of a concrete Widget subclass. [...]
複製程式碼
  1. findRenderObject() → RenderObject
The current RenderObject for the widget. If the widget is a RenderObjectWidget, this is the render object that the widget created for itself. Otherwise, it is the render object of the first descendant RenderObjectWidget. [...]
複製程式碼
  1. inheritFromElement(InheritedElement ancestor, { Object aspect }) → InheritedWidget
Registers this build context with ancestor such that when ancestor's widget changes this build context is rebuilt. [...]
複製程式碼
  1. inheritFromWidgetOfExactType(Type targetType, { Object aspect }) → InheritedWidget
Obtains the nearest widget of the given type, which must be the type of a concrete InheritedWidget subclass, and registers this build context with that widget such that when that widget changes (or a new widget of that type is introduced, or the widget goes away), this build context is rebuilt so that it can obtain new values from that widget. [...]
複製程式碼
  1. rootAncestorStateOfType(TypeMatcher matcher) → State
Returns the State object of the furthest ancestor StatefulWidget widget that matches the given TypeMatcher. [...]
複製程式碼
  1. visitAncestorElements(bool visitor(Element element)) → void
Walks the ancestor chain, starting with the parent of this build context's widget, invoking the argument for each ancestor. The callback is given a reference to the ancestor widget's corresponding Element object. The walk stops when it reaches the root widget or when the callback returns false. The callback must not return null. [...]
複製程式碼
  1. visitChildElements(ElementVisitor visitor) → void
Walks the children of this widget. [...]
複製程式碼

0x05 參考文獻

docs.flutter.io/flutter/wid…

相關文章