将数据从窗口小部件发送到另一个窗口小部件

时间:2020-07-25 20:14:48

标签: flutter dart flutter-provider state-management flutter-widget

我想将数据从小部件发送到另一个小部件,在我的示例中,我想将一些过滤器数据从FilterScreen.dart发送到ShopScreen.dart 它工作正常,但我不知道我在做什么是正确的?

在过滤器模型文件中:

class FilterData with ChangeNotifier {
  bool isFreeShipping;
  bool isSomeThingElse;

  FilterData({this.isFreeShipping = false, this.isSomeThingElse = false});

  void setFreeShippingValue(bool newval) {
    isFreeShipping = newval;
    notifyListeners();
  }

  void setSomeThingElseValue(bool newval) {
    isSomeThingElse = newval;
    notifyListeners();
  }
}

在main.dart中:

return ChangeNotifierProvider(
      create: (context) => FilterData(),
      child: MaterialApp(
       .........
    )
);

在标签屏幕中:

class TabsScreen extends StatefulWidget {
  @override
  _TabsScreenState createState() => _TabsScreenState();
}

class _TabsScreenState extends State<TabsScreen> {
  List<Map<String, Object>> _pages;
  int _selectedPageIndex = 0;

  @override
  void initState() {
    _pages = [
      {
        'page': ShopScreen(),
        'title': 'shop',
      },
      {
        'page': FilterScreen(),
        'title': 'filter',
      },
    ];
    super.initState();
  }

  void _selectPage(int index) {
    setState(() {
      _selectedPageIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_pages[_selectedPageIndex]['title']),
      ),
      drawer: DrawerApp(),
      body: _pages[_selectedPageIndex]['page'],
      bottomNavigationBar: BottomNavigationBar(
        onTap: _selectPage,
        backgroundColor: Theme.of(context).primaryColor,
        unselectedItemColor: Colors.white,
        selectedItemColor: Theme.of(context).accentColor,
        currentIndex: _selectedPageIndex,
        // type: BottomNavigationBarType.fixed,
        items: [
          BottomNavigationBarItem(
            backgroundColor: Theme.of(context).primaryColor,
            icon: Icon(Icons.shop),
            title: Text('Shop'),
          ),
          BottomNavigationBarItem(
            backgroundColor: Theme.of(context).primaryColor,
            icon: Icon(Icons.search),
            title: Text('Filter'),
          ),
        ],
      ),
    );
  }
}

在FilterScreen.dart中:

class FilterScreen extends StatefulWidget {
  @override
  _FilterScreenState createState() => _FilterScreenState();
}

class _FilterScreenState extends State<FilterScreen> {
  @override
  Widget build(BuildContext context) {
    final data = Provider.of<FilterData>(context);

    return Container(
      child: Center(
        child: Expanded(
          child: ListView(
            children: <Widget>[
              SwitchListTile(
                  title: Text('Free Shipping'),
                  value: data.isFreeShipping,
                  subtitle: Text('get free shipping products'),
                  onChanged: (newValue) {
                    data.setFreeShippingValue(newValue);
                  }),
              SwitchListTile(
                  title: Text('Some thing else'),
                  value: data.isSomeThingElse,
                  subtitle: Text('get filtred products'),
                  onChanged: (newValue) {
                    data.setSomeThingElseValue(newValue);
                  }),
            ],
          ),
        ),
      ),
    );
  }
}

在ShopScreen.dart中:

class ShopScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final data = Provider.of<FilterData>(context);

    return Container(
      child: Center(
        child: Text(
            data.isFreeShipping ? 'get favorite Products' : 'get all products'),
      ),
    );
  }
}

enter image description here

1 个答案:

答案 0 :(得分:0)

对于大多数开发人员来说,您的问题确实很痛苦,就像我不知道它是如何工作的!

因此,如果您听不懂。这样做有两个原因:

  • 您只是盲目地遵循了教程或文档,没有时间限制
  • 您不了解Flutter Provider State Management works的方式。因此,为此,请仔细阅读以下内容:

所以,现在让我们跳到代码。 您的代码如何工作?

造成这一情况的原因有很多:

1。提供商包装:如果您仔细查看main.dart代码,就可以做到

return ChangeNotifierProvider(
      create: (context) => FilterData(), // here you define the ChangeNotifier class
      child: MaterialApp(
       .........
    )
);

现在查看上面的代码,您会发现,每当用ChangeNotifierProvider()包装应用程序时,只要您在其中提供的类中的状态发生了变化,它就会始终重建 >,在这种情况下为FilterData()。任何发生的更改都将反映在整个应用中,因为ChangeNotifierProvider()的整个应用都将继续重建直子的状态,在这种情况下,您的MaterialApp()将被包装。

2。来自ChangeNotifier类的NotifyChanges::如果您查看FilterData,它是负责应用重建的应用,它由ChangeNotifierProvider()包装。

让我们看看如何:

  void setFreeShippingValue(bool newval) {
    isFreeShipping = newval;
    notifyListeners();
  }

  void setSomeThingElseValue(bool newval) {
    isSomeThingElse = newval;
    notifyListeners();
  }

如果您仔细查看上面我在您的FilterData类中的代码中提到的方法,则它们具有notifyListeners()。这些是负责任的,每当调用这两种方法时,它都会通知ChangeNotifierListener重建小部件,因此,每次使用这两种方法中的任何一种时,您都会看到更新的数据

3。在FilterScreen的FilterData中使用NotifyListeneres方法:因此,再次仔细观察第2点中提到的内容,我们会看到应该将method方法调用为在ChangeNotifierProvider()

的直接子级应用程序中进行更改
                 SwitchListTile(
                  title: Text('Free Shipping'),
                  value: data.isFreeShipping,
                  subtitle: Text('get free shipping products'),
                  onChanged: (newValue) {
                    data.setFreeShippingValue(newValue);
                  }),
              SwitchListTile(
                  title: Text('Some thing else'),
                  value: data.isSomeThingElse,
                  subtitle: Text('get filtred products'),
                  onChanged: (newValue) {
                    data.setSomeThingElseValue(newValue);
                  }),

因此,当您调用onChanged中的任何方法时,它会立即通知Provider,该值已更改,并且应用程序将重建,并且当您切换到另一个选项卡时,您会看到更新结果如魔术。

最重要的:您的final data = Provider.of<FilterData>(context);是Provider类的实例,它触发该方法来帮助通知ChangeNotifierProvider()在应用中进行更改

所以映射是这样的:

                                                          Listens to the change
FilterData {setFreeShippingValue, setSomeThingElseValue} <----------------------> ChangeNotifierProvider() REBUILDS MATERIALAPP()