//platform: Android
//author: 'mulegame'
import 'package:flutter/material.dart';
class TabNavigator extends StatefulWidget {
@override
State<StatefulWidget> createState() => _TabNavigator();
}
// abstract class State<T extends StatefulWidget> with Diagnosticable{...}
class _TabNavigator extends State<TabNavigator> {
@override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
重点1:
@override
State<StatefulWidget> createState() => _TabNavigator();
抛砖引玉: 为什么在TabNavigator中必须要重写(@override)State中的createState()?
查看State抽象类源码时发现:
abstract class State<T extends StatefulWidget> with Diagnosticable {
/// The current configuration.
///
/// A [State] object's configuration is the corresponding [StatefulWidget]
/// instance. This property is initialized by the framework before calling
/// [initState]. If the parent updates this location in the tree to a new
/// widget with the same [runtimeType] and [Widget.key] as the current
/// configuration, the framework will update this property to refer to the new
/// widget and then call [didUpdateWidget], passing the old configuration as
/// an argument.
T get widget => _widget!;
T? _widget;
/// The current stage in the lifecycle for this state object.
///
/// This field is used by the framework when asserts are enabled to verify
/// that [State] objects move through their lifecycle in an orderly fashion.
_StateLifecycle _debugLifecycleState = _StateLifecycle.created;
/// Verifies that the [State] that was created is one that expects to be
/// created for that particular [Widget].
bool _debugTypesAreRight(Widget widget) => widget is T;
/// The location in the tree where this widget builds.
///
/// The framework associates [State] objects with a [BuildContext] after
/// creating them with [StatefulWidget.createState] and before calling
/// [initState]. The association is permanent: the [State] object will never
/// change its [BuildContext]. However, the [BuildContext] itself can be moved
/// around the tree.
///
/// After calling [dispose], the framework severs the [State] object's
/// connection with the [BuildContext].
BuildContext get context {
assert(() {
if (_element == null) {
throw FlutterError(
'This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n'
'Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',
);
}
return true;
}());
return _element!;
}
大意说,State这个对象关联着上下文,既然是StatefulWidget,那么势必会进行State[状态|行为]上下文关联操作,比如,A,B两个页面互相传递参数等等
编码片断部分判断了 _element == null (element 元素),这里比较好理解,如果bool return false 那么就说明“承载state上下文的widget不存在”那么,就没有继续下去的必要了.
回归正题: 哪里针对createState()进项操作了呢? 莫慌,继续往下看源码,发现了一大堆关于State操作的方法,尤其是:
/// {@template flutter.widgets.State.initState}
/// If a [State]'s [build] method depends on an object that can itself
/// change state, for example a [ChangeNotifier] or [Stream], or some
/// other object to which one can subscribe to receive notifications, then
/// be sure to subscribe and unsubscribe properly in [initState],
/// [didUpdateWidget], and [dispose]:
///
/// * In [initState], subscribe to the object.
/// * In [didUpdateWidget] unsubscribe from the old object and subscribe
/// to the new one if the updated widget configuration requires
/// replacing the object.
/// * In [dispose], unsubscribe from the object.
///
/// {@endtemplate}
///
/// You cannot use [BuildContext.dependOnInheritedWidgetOfExactType] from this
/// method. However, [didChangeDependencies] will be called immediately
/// following this method, and [BuildContext.dependOnInheritedWidgetOfExactType] can
/// be used there.
///
/// Implementations of this method should start with a call to the inherited
/// method, as in `super.initState()`.
@protected
@mustCallSuper
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
if (kFlutterMemoryAllocationsEnabled) {
MemoryAllocations.instance.dispatchObjectCreated(
library: _flutterWidgetsLibrary,
className: '$State',
object: this,
);
}
}
原来如此, initState() 从字面理解就是初始化.且从上下文环境中关系着StatefulWidget的生命周期.
重点2:
abstract class StatefulWidget extends Widget {
/// Initializes [key] for subclasses.
const StatefulWidget({ super.key });
/// Creates a [StatefulElement] to manage this widget's location in the tree.
///
/// It is uncommon for subclasses to override this method.
@override
StatefulElement createElement() => StatefulElement(this);
/// Creates the mutable state for this widget at a given location in the tree.
///
/// Subclasses should override this method to return a newly created
/// instance of their associated [State] subclass:
///
/// ```dart
/// @override
/// State<SomeWidget> createState() => _SomeWidgetState();
/// ```
///
/// The framework can call this method multiple times over the lifetime of
/// a [StatefulWidget]. For example, if the widget is inserted into the tree
/// in multiple locations, the framework will create a separate [State] object
/// for each location. Similarly, if the widget is removed from the tree and
/// later inserted into the tree again, the framework will call [createState]
/// again to create a fresh [State] object, simplifying the lifecycle of
/// [State] objects.
@protected
@factory
State createState();
}
哦!找到了 StatefulWidget的爹,原来是Widget
在末尾存在着一个 createState() 而且一目了然. (注意@factory工厂修饰符)
关键部分来了:
@override
StatefulElement createElement() => StatefulElement(this);
创建元素:
/// An [Element] that uses a [StatefulWidget] as its configuration.
class StatefulElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatefulElement(StatefulWidget widget)
: _state = widget.createState(),
super(widget) {
assert(() {
if (!state._debugTypesAreRight(widget)) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('StatefulWidget.createState must return a subtype of State<${widget.runtimeType}>'),
ErrorDescription(
'The createState function for ${widget.runtimeType} returned a state '
'of type ${state.runtimeType}, which is not a subtype of '
'State<${widget.runtimeType}>, violating the contract for createState.',
),
]);
}
return true;
}());
assert(state._element == null);
state._element = this;
assert(
state._widget == null,
'The createState function for $widget returned an old or invalid state '
'instance: ${state._widget}, which is not null, violating the contract '
'for createState.',
);
state._widget = widget;
assert(state._debugLifecycleState == _StateLifecycle.created);
}
大概流程梳理:
State->获取Widget并且管理着上下文,掏粪的活交给 StatefulWidget 与 StatefulElement。
State比较优雅的坐着办公室喝着咖啡只是管理着Widget的生命周期...
自从哥撸了createState()开始,就给自己挖了个坑:
State<StatefulWidget> createState() => _TabNavigator();
到这里开始BuildContext:
class _TabNavigator extends State<TabNavigator> {
@override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
也就是说,为什么当自己实现_TabNavigator时,必须要重写build方法,也理解了到底为什么需要BuildContext参数,因为没有context,State这个老板没办法管理你_TabNavigator的生命周期。而State源码中的各种生命周期管理方法像极了老板的种种手段.
so, 原来我才是那个掏粪工...