简体   繁体   English

将数据从小部件发送到 flutter 中的另一个小部件

[英]send data from widget to another widget in flutter

I want to send data from widget to another widget, in my example i want to send some filter data from FilterScreen.dart to ShopScreen.dart it works fine but i dont know is what i'm doing is correct?我想将数据从小部件发送到另一个小部件,在我的示例中,我想将一些过滤器数据从 FilterScreen.dart 发送到 ShopScreen.dart 它工作正常,但我不知道我在做什么是正确的?

in filter model file:在过滤器 model 文件中:

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();
  }
}

in main.dart:在 main.dart 中:

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

in tabs screen:在标签屏幕中:

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'),
          ),
        ],
      ),
    );
  }
}

in FilterScreen.dart:在 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);
                  }),
            ],
          ),
        ),
      ),
    );
  }
}

in ShopScreen.dart:在 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在此处输入图像描述

Your question indeed is a pain for most of the developers, which is like I don't know how it works!您的问题确实是大多数开发人员的痛苦,就像我不知道它是如何工作的!

So, if you are not able to understand.所以,如果你无法理解。 there are two reasons to that:有两个原因:

  • You just blindly followed the tutorial or documentation, cos of the time constraints您只是盲目地遵循教程或文档,因为时间限制
  • You did not understand how Flutter Provider State Management works .你不明白Flutter Provider State Management works的。 So, for that, do read upon these:因此,为此,请阅读以下内容:

So, now let us jump to the code.所以,现在让我们跳到代码。 How your code works?你的代码是如何工作的?

There are multiple things which are responsible for this:有很多事情要为此负责:

1. Provider Wrap: If you closely look into the main.dart code, you have done this 1. Provider Wrap:如果你仔细查看main.dart代码,你已经做到了

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

Now looking at the above code, you see, whenever you wrap the app with the ChangeNotifierProvider() , it always rebuilds whenever there is a state change in the class which you have provided inside that , in this case FilterData() .现在查看上面的代码,您会看到,每当您使用ChangeNotifierProvider()包装应用程序时,只要您在其中提供的 class 中存在 state 更改(在本例中为FilterData() ),它总是会重新构建。 Any changes happens will reflect in the whole app, cos, ChangeNotifierProvider() , is keep rebuilding the state of the immediate child, in this case your, MaterialApp() , which is wrapped.发生的任何更改都将反映在整个应用程序中,因为ChangeNotifierProvider()正在继续重建直系孩子的 state,在这种情况下,您的MaterialApp()已被包装。

2. NotifyChanges from the ChangeNotifier class: If you look at your FilterData , it is the one which is responsible for the rebuilding of the app, which is wrapped by the ChangeNotifierProvider() . 2.来自 ChangeNotifier class 的 NotifyChanges:如果您查看FilterData ,它是负责重建应用程序的那个,它由ChangeNotifierProvider()包装。

Let us see how:让我们看看如何:

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

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

If you closely take a look at the methods, which I mentioned in the above code from your FilterData class only, they have notifyListeners() .如果您仔细查看我在上述代码中仅从您的FilterData class 中提到的方法,它们具有notifyListeners() These are the ones, which is responsible, whenever your two methods called, it notifies the ChangeNotifierListener to rebuild the widget, and hence you see the updated data every time, you use any of the two methods这些是负责的,每当您调用两个方法时,它都会通知ChangeNotifierListener重建小部件,因此您每次都会看到更新的数据,您可以使用这两种方法中的任何一种

3. Using NotifyListeneres method from the FilterData in FilterScreen: So, again if we look closely at the thing which we have mentioned in the point 2 , we see that, the method method should be called to make changes in the App which is the immediate child of ChangeNotifierProvider() 3.使用FilterScreen中FilterData中的NotifyListeneres方法:所以,再次仔细观察我们在第2点中提到的事情,我们看到,应该调用方法方法来在App中进行更改,即立即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);
                  }),

So, when you call any of the methods in your onChanged , it straight away notifies the Provider that, the value has been changed, and the app rebuilds, and when you switch to the other tab, you see updated result like magic.因此,当您调用onChanged中的任何方法时,它会立即通知 Provider 值已更改,并且应用程序会重新构建,当您切换到另一个选项卡时,您会看到更新的结果,就像魔术一样。

MOST IMPORTANT: Your final data = Provider.of<FilterData>(context);最重要的:您的final data = Provider.of<FilterData>(context); , is an instance of the Provider class, which trigger the method to help notify the ChangeNotifierProvider() to make changes in the app , 是 Provider class 的一个实例,它触发了帮助通知ChangeNotifierProvider()在应用程序中进行更改的方法

So the mapping is like that:所以映射是这样的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM