前言

首先我们看看官方的定义:

[BuildContext] objects are actually [Element] objects. The [BuildContext] interface is used to discourage direct manipulation of [Element] objects. [BuildContext] 对象实际上是 [Element] 对象。 [BuildContext] 接口用于阻止直接操作 [Element] 对象。

根据官方这段注释,可以了解到BuildContext 实际上就是 Element 对象,产生的意义主要是为了防止开发者直接操作 Element 对象。

如何使用BuildContext

写一段大家很熟悉的代码

c } l a i } s n o s t i s } d e ) _ _ t _ ; M c _ S c y o i t o H u n a u o n c t n m t r e t e e e ( e P r m ( r a e ) + g = n + e t { ; S 0 C t ; o a u t n e t e e r x ( t ) e n { d s S t a t e < M y H o m e P a g e > {

这里有同学好奇,_counter++;不写在setState的回调方法里可以生效吗?答案是可以的。但是我更推荐把和状态更新相关的操作,放在回调里面。这样更加的工程化管理。因为一个项目经过长时期的更新,你可能无法分清,这个方法里面的setState,是不是实际上起作用了,会造成代码冗余。

上面的代码也可以写成这样

c } l a i } s n o ( s t i c d o _ _ _ n M c _ c t y o i o e H u n u x o n c n t m t r t e e e e a P r m r s a e + g = n + E e t ; l S 0 C e t ; o m a u e t n n e t t e ) e r . x ( m t ) a e r n { k d N s e e S d t s a B t u e i < l M d y ( H ) o ; m e P a g e > {

为什么会有同样的作用呢?那我们看看setState的源码吧

} o i a a } f a } _ d s s ( i s ( e s s i } i } r ) n s i } r ) l s e e f f e ) a e f e ) e e r r t ; l r ] t ; m t t t u t ( ) u e S ( ( _ _ r d ( r ; r n t f ( d d n y ( e n t a n ) e e n ) s ! t b b t a u t . e ! { u u r m { l r m ( = g g u i t u a V L L e c e r o n i i ; i ; k i u f f r s N d l e e e e C l c c s F e a ) y y u u d l ; c c l t s l l l t u B b e e r u a S S = e i c t t ) l k a a f d t t n { ( f e e ( ) n ) ; ) = = = = a { s _ _ S S d t t y a a n t t a e e m L L i i i c f f ; e e c c y y c c l l e e . . d c e r f e u a n t c e t d ) & { & ! m o u n t e d ) {

那么我们就清楚了,BuildContext实际上就是Widget树中特定位置所对应的实例Element

使用BuildContext时,应该注意作用域

举个例子

i c } c } m o l l p i a @ W } a @ W } o d s o i s o i r s v d r ) s v d r ) t m e g e ; e g e ; a M r e t t h ) N r e t a ) b ) ' i y r t u i o , e r t u p , o , p n A i r t m b ) w i r p t d c a ( p d b n l e o , W d b n B i y h c ) p e u e : d c i e u a t : i k i M : y h d i S r l l a = e l a S : i g l c : e C d g > x d t ' c l e d a : e : e t ( e T a C d o } c t f A n : r e B r e f e : n , h ( f p T t T f u n u i s f n P N i e B o p e e e l n d i a t o t F r a l x u l B x r x u A s l l l e l e v d t i d a t ( t t p d A F d r a s i : e l ( r ( ( t p S C p l ( ( t s g M n d ( " " e ( t o p u B e a a T d C t t r M a n ( t u d t t e s o h h / y t t t t : o e x n i i m A e e e t r r t S t s s a p l x r o . i ( t e t p e t ' n o a ' a x i i e ( s , ( f l t t s s r ) s c { ( P e i ) W o c a l c t b a ; i n o g e o i o l d t n e s n t d . g e t R s t l y d e x e o ' W e e " a t t x u ) i x " ) r ) t t ) d t ) , t { { ) e , g ) , ' . ( e { ; p b t u u s i { h l ( d e r : ( c o n t e x t ) = > N e w W i d g e t ( ) ) ) ;

运行一下,发现会报错:提示当前的context找不到Navigator。 我们知道NavigatorMaterialApp为我们提供的,但是当前的调用的context,实际上是MyApp拥有的实例,并不是MaterialApp对应的context。 那我们可以改造一下:

c } l a @ W } s o i s v d r ) ) e g e N , ) ; M r e t t h o a M } c ; y r t u i o n v a , h A i r t m b P i t i ) p d b n l e o r g e l , p e u e : d c b e a r d } i M : y h u s t i : , e l a S : i i r s o a x d t ' c l l e e r l T t ( e T a C d d t d . P e e B r e f e : e u : o a x n u i s f n r r f g t d i a t o t B : n ( e ( s l l l e u c R ' d A F d r i ( F o o S C p l ( ( l c l { n u t o p u d o a t t a n ( t e n t e e t t t r t B x ( e e e ( e u t b l x r x t ) u ' e t ' t t . i ) s , ) o p l ) s c n u d , W o { ( s e i n h r d t ( : g e e x ( t t c ) o { { n t e x t ) = > N e w W i d g e t ( ) ) ) ;