flutter context踩坑


下面代碼有三個button,內容都是一樣的,只不過包裝方式不同。

第一個是沒有包裝的,第二個用Builder包了一層,第三個封裝成了StatelessWidget。

運行一下,第一個button會報如下錯誤:

 

是說調用的Scaffod.of(context)找不到Scaffold。

import 'package:flutter/material.dart';

void main() => runApp(BuilderApp());

class BuilderApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BuilderHomePage(),
    );
  }
}

class BuilderHomePage extends StatefulWidget {
  @override
  _BuilderHomePageState createState() => _BuilderHomePageState();
}

class _BuilderHomePageState extends State<BuilderHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Hello"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              onPressed: () {
                Scaffold.of(context).showSnackBar(
                    new SnackBar(content: Text("Hello  SnackBar1")));
              },
              child: Text("Test"),
            ),
            Builder(
              builder: (BuildContext context) {
                return RaisedButton(
                  onPressed: () {
                    Scaffold.of(context).showSnackBar(
                        new SnackBar(content: Text("Hello  SnackBar2")));
                  },
                  child: Text("Builder SnackBar"),
                );
              },
            ),
            WidgetTest()
          ],
        ),
      ),
    );
  }
}


class WidgetTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child:     RaisedButton(
        onPressed: () {
          Scaffold.of(context).showSnackBar(
              new SnackBar(content: Text("Hello  SnackBar3")));
        },
        child: Text("No Builder SnackBar"),
      ),
    );
  }
}

 

分析一下:

這是Scaffold.of(context)的源碼

 

可以看到這個方法返回的是findAncestorStateOfType()。其實所有.of(context).xxx這樣的方法都是調用這個東西。

點進去看看:

 

可以看到這個方法是在依次向上遍歷該widget的祖先,直到找到一個符合參數類型的祖先就退出。

注意最開始賦值是把當前widget的_parent賦給了ancestor,所以是從當前widget的父節點開始找的。

 

那么就很容易判斷了:

第一個button的context復用了build函數的context(android studio很貼心的會高亮兩個context的連接關系) 

 

第二個button用Builder套了一層,它的context是Builder的builder函數的參數context

 

 

 第三個button的context是StatelessWidget的build函數參數的context,就不截圖了。

 

由於第一個button的context和scaffold是同一個,所以從它的_parent往上找肯定找不到scaffold,所以報錯。

另外兩個button都是scaffold的子節點,他倆的_parent恰好就是scaffold,所以不會報錯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM