- BuildContext
- Widget的绘制
- 事件传递机制
- 手势
- key的作用
- 框架原理
- Builder里的context的源头
- Key的作用
七、Builder
里的context
是包裹这个Builder
的Widget
的context
,每个Widget
都有自己的context
,举个例子:
上图中
builder: (context)
参数里的context是Positioned的context这个概念很重要,因为如果你使用
Scaffold.of(context).showSnackBar
方法显示SnackBar
的话,使用错了context会报错,因为你使用的context可能不包含Scaffold,系统找不到就报错了,系统源码如下:
//scaffold.dart
static ScaffoldState of(BuildContext context, { bool nullOk = false }) {
assert(nullOk != null);
assert(context != null);
final ScaffoldState result = context.ancestorStateOfType(const TypeMatcher<ScaffoldState>());
if (nullOk || result != null)
return result;
throw FlutterError(
'Scaffold.of() called with a context that does not contain a Scaffold.\n'
'No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). '
'This usually happens when the context provided is from the same StatefulWidget as that '
'whose build function actually creates the Scaffold widget being sought.\n'
'There are several ways to avoid this problem. The simplest is to use a Builder to get a '
'context that is "under" the Scaffold. For an example of this, please see the '
'documentation for Scaffold.of():\n'
' https://docs.flutter.io/flutter/material/Scaffold/of.html\n'
'A more efficient solution is to split your build function into several widgets. This '
'introduces a new context from which you can obtain the Scaffold. In this solution, '
'you would have an outer widget that creates the Scaffold populated by instances of '
'your new inner widgets, and then in these inner widgets you would use Scaffold.of().\n'
'A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, '
'then use the key.currentState property to obtain the ScaffoldState rather than '
'using the Scaffold.of() function.\n'
'The context used was:\n'
' $context'
);
}
//framework.dart
@override
State ancestorStateOfType(TypeMatcher matcher) {
assert(_debugCheckStateIsActiveForAncestorLookup());
Element ancestor = _parent;
while (ancestor != null) {
if (ancestor is StatefulElement && matcher.check(ancestor.state))
break;
ancestor = ancestor._parent;
}
final StatefulElement statefulAncestor = ancestor;
return statefulAncestor?.state;
}
可以看到framework.dart
文件里的ancestorStateOfType
方法会从参数context
寻找匹配的类型,也就是TypeMatcher<ScaffoldState>
中的泛型类型ScaffoldState
,找不到就抛出了异常。
网友评论