Flutter 中由 BuildContext 引起的血案

今天和各位分享一個博主在實際開發中遇到的問題,以及解決方法。廢話很少說,咱們先來看需求:
咱們要作一個iOS風格的底部菜單彈出組件,具體涉及showCupertinoModalPopup()方法,該方法被執行後,會出現以下圖相似所示的菜單彈出視圖:
bash

在這裏插入圖片描述
相信這個彈出菜單視圖都有見過吧?下面重點來了:在本次的項目需求中,該視圖的 選項文字是由Server端返回的。也就是說,這些選項的內容和個數都不固定,所以不能將其在代碼中寫固定值。
爲了簡化代碼以突出重點,下面放上我在一開始的實現方案:

openActionSheet() {
    List<Widget> menuWidgets = new List();
    menuItems.forEach((element) {
      menuWidgets.add(CupertinoActionSheetAction(
        child: Text(element),
        onPressed: () {
          Navigator.pop(context);
          debugPrint("操做$element被執行「); }, isDefaultAction: true, )); }); showCupertinoModalPopup( context: context, builder: (buildContext) { return CupertinoActionSheet( title: Text('測試菜單'), message: Text('點擊菜單項試試吧!'), actions: menuWidgets); }); } 複製代碼

如上述代碼所示,openActionSheet()是顯示該組件的方法。其中,showCupertinoModalPopup()爲Flutter SDK內置方法,其做用即顯示這個組件;再其上面的循環以及List聲明、賦值等操做實際上就是在動態添加菜單項。menuItems類型是List<String>。
經過對代碼的解釋,相信你們可以一目瞭然地看出,當某個菜單項被點擊時,整個菜單組件消失,並打印Debug Log(對應爲真實項目要執行的操做)。
你們以爲上述代碼有問題嗎?若是有問題,問題在哪兒呢?
如今公佈答案:這段代碼有問題!
上述代碼執行時,當用戶點擊菜單項後,其運行結果並不是如咱們預想的那樣:菜單組消失並輸出Log,而變成了:整個頁面被Pop,菜單組保留,並輸出Log!
這是什麼緣由呢?
實際上,罪魁禍首就在咱們循環遍歷賦值操做時的這條語句:測試

Navigator.pop(context);
複製代碼

這裏的context是整個頁面的BuildContext,而非菜單組的。這裏咱們要明確一個概念——咱們想Pop誰,必定要用誰的BuildContext對象。
在這裏,正確的BuildContext對象是誰呢?它在這裏:ui

showCupertinoModalPopup(
    context: context,
    builder: (buildContext) {
      return CupertinoActionSheet(
          title: Text('測試菜單'),
          message: Text('點擊菜單項試試吧!'),
          actions: menuWidgets);
    }
);
複製代碼

注意到了嗎?上面第三行括號裏的buildContext纔是咱們真正要用的對象。所以,正確的作法是什麼呢?spa

openActionSheet() {
    BuildContext tempContext;
    List<Widget> menuWidgets = new List();
    menuItems.forEach((element) {
      menuWidgets.add(CupertinoActionSheetAction(
        child: Text(element),
        onPressed: () {
          Navigator.pop(tempContext);
          debugPrint("操做$element被執行");
        },
        isDefaultAction: true,
      ));
    });

    showCupertinoModalPopup(
        context: context,
        builder: (buildContext) {
          tempContext = buildContext;
          return CupertinoActionSheet(
              title: Text('測試菜單'),
              message: Text('點擊菜單項試試吧!'),
              actions: menuWidgets);
        });
  }
複製代碼

如上所示,咱們只需將正確的對象「帶」到其做用域外面就能夠了。
好了,這就是本篇文章的所有內容,但願可以對你有所幫助!debug

相關文章
相關標籤/搜索