首页 > 解决方案 > 如何使用 Provider 在两个小部件之间共享数据?

问题描述

我有两个小部件,我在下面共享代码,在第一张卡片小部件中用于用户选择成分,第二张卡片将用于显示所选成分,初始两个屏幕都是空的,当用户添加成分时,两个小部件都将根据选择重建成分,我可以处理它在第一个小部件中显示,但是当它更改时我无法处理显示 selectedIngredient 列表数据,我知道我必须使用提供程序包但我无法为我的代码实现,我卡住了请帮助我.. .


class AddIngredientsCard extends StatefulWidget {
  AddIngredientsCard({this.subCategoryId,this.subCategoryCardId});
  final int subCategoryCardId;
  final int subCategoryId;
  @override
  _AddIngredientsCardState createState() => _AddIngredientsCardState();
}
class _AddIngredientsCardState extends State<AddIngredientsCard>{
  String textValue;
  double _animatedContainerHeight=350;
  double _top=15;
  double _right=30;
  double _left=30;
  double _bottom=15;
  List<String> items= [];
  List<String>selectedIngredients=[];

  @override
  void initState() {
    ingredients=ingredients..sort((String a, String b)=>a.compareTo(b));
    items.addAll(ingredients);
    super.initState();
  }

  void filterSearchResults(String query) {
    List<String> searchList = [];
    searchList.addAll(ingredients);
    if(query.isNotEmpty) {
      List<String> listData = [];
      searchList.forEach((item) {
        if(item.contains(query)) {
          listData.add(item);
        }
      });
      setState(() {
        items.clear();
        items.addAll(listData);
      });
      return;
    } else {
      setState(() {
        items.clear();
        items.addAll(ingredients);
      });
    }
  }



  void _toggleCardSize(){
    _top==15?_top=7.5: _top=15;
    _right==30?_right=7.5: _right=30;
    _left==30?_left=7.5: _left=30;
    _bottom==15?_bottom=7.5: _bottom=15;
  }

  void _toggleCardHeight(){
    _animatedContainerHeight==350?_animatedContainerHeight=600:_animatedContainerHeight=350;
  }

  @override
  Widget build(BuildContext context) {


    return AnimatedPadding(
      duration: Duration(milliseconds: 500),
      curve: Curves.linearToEaseOut,
      padding:EdgeInsets.only(top: _top,right: _right,left: _left,bottom: _bottom),
      child: AnimatedContainer(
          height:_animatedContainerHeight,
          duration: Duration(milliseconds: 500),
          child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Container(
                  decoration: BoxDecoration(
                    border:Border.all(style: BorderStyle.solid, width: 1),
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(90),
                  ),
                  height: 60,
                  child: TextField(
                    style: TextStyle(
                      color: Colors.black,
                      fontFamily:"OpenSans",
                      fontSize: 20,
                    ),
                    textAlign: TextAlign.center,
                    textAlignVertical: TextAlignVertical.center,
                    onChanged: (value){
                      if(value.length>0){
                        value=value[0].toUpperCase()+value.substring(1);
                        filterSearchResults(value);
                      }
                      else{
                        filterSearchResults(value);
                      }
                    },
                    decoration: InputDecoration(
                      prefixIcon: Icon(Icons.search),
                      border:OutlineInputBorder(
                        borderRadius: BorderRadius.circular(90),
                        borderSide: BorderSide(
                          color: kColorTheme10,
                        ),
                      ),
                      hintText: "Malzeme ismi arayın",
                      hintStyle: TextStyle(
                        color: Colors.black.withOpacity(0.5),
                        fontFamily: "OpenSans",
                      ),
                    ),
                  ),
                ),
                SizedBox(height: 2,),
                Expanded(
                  flex: _animatedContainerHeight==350?1:4,
                  child: ListView.builder(
                    scrollDirection: Axis.horizontal,
                    shrinkWrap: true,
                    itemCount: selectedIngredients.length,
                    itemBuilder: (context,index){
                      return Padding(
                        padding: EdgeInsets.all(1),
                        child: GestureDetector(
                          onTap: (){
                            setState(() {
                              selectedIngredients.removeAt(index);
                              if (selectedIngredients.length == 0) {
                                _toggleCardHeight();
                                _toggleCardSize();
                                }
                              }
                            );
                          },
                          child: Container(
                            decoration: BoxDecoration(
                              color: kColorTheme11,
                              borderRadius: BorderRadius.circular(90),
                              border: Border.all(style: BorderStyle.solid,width: 1),
                            ),
                            child: Padding(
                              padding: EdgeInsets.all(8.0),
                              child: Row(
                                crossAxisAlignment: CrossAxisAlignment.center,
                                children: [
                                  BorderedText(strokeColor: Colors.black,strokeWidth: 5,child: Text(selectedIngredients[index],style:
                                    TextStyle(fontWeight: FontWeight.bold,fontSize:20,color: Colors.white),)),
                                  SizedBox(width: 5,),
                                  Icon(
                                    Icons.cancel,color: Colors.white,size: 20,
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      );
                    }
                  ),
                ),
                SizedBox(height: 2,),
                Expanded(
                  flex: 40,
                  child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: items.length,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: EdgeInsets.all(2.0),
                        child: GestureDetector(
                          onTap: (){
                            setState(() {
                              if(selectedIngredients.length==0){
                                selectedIngredients.add("${items[index]}");
                                _toggleCardHeight();
                                _toggleCardSize();
                              }
                              else{
                                selectedIngredients.add("${items[index]}");
                              }
                            });
                          },
                          child: Container(
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(90),
                              border: Border.all(style:BorderStyle.solid,width: 1),
                              color: Colors.white54,

                            ),
                            child: Padding(
                              padding: EdgeInsets.all(5),
                              child: Text('${items[index]}',style: TextStyle(fontWeight: FontWeight.bold),)),
                          ),
                        ),
                      );
                    },
                  ),
                ),
                SizedBox(height: 8,),
                Expanded(
                  flex: _animatedContainerHeight==350?1:4,
                  child: Row(
                    children: [
                      Expanded(
                        child: Container(
                          decoration: BoxDecoration(
                            color:  _animatedContainerHeight==350?categoryModels[widget.subCategoryId].
                            subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.1):kColorTheme11,
                            borderRadius: BorderRadius.circular(20),
                            border: _animatedContainerHeight==350?null:
                            Border.all(style: BorderStyle.solid,width: 2),
                          ),
                          child: Padding(
                            padding: EdgeInsets.all(5),
                            child: GestureDetector(
                              onTap: (){
                                AddIngredientsAmount(subCategoryId:widget.subCategoryId,subCategoryCardId: widget.subCategoryId,selectedIngredients: selectedIngredients,);
                                  /////////////////////////////////////// => isPageSaved için Provider eklenecek...
                              },
                              child: Center(child: BorderedText(strokeWidth:3,strokeColor: Colors.black,child:
                              Text("KAYDET",style: TextStyle(fontSize: 25, fontWeight: FontWeight.w900 ,color: Colors.white))),
                              ),
                            ),
                          ),
                        )
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
          decoration: BoxDecoration(
            border: Border.all(style: BorderStyle.solid, width: 1),
            borderRadius: BorderRadius.circular(30),
            color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
          )
      ),
    );
  }
}

class AddIngredientsAmount extends StatefulWidget {
  AddIngredientsAmount({this.subCategoryId,this.subCategoryCardId, this.selectedIngredients});
  final List selectedIngredients;
  final int subCategoryCardId;
  final int subCategoryId;
  @override
  _AddIngredientsAmountState createState() => _AddIngredientsAmountState();
}
class _AddIngredientsAmountState extends State<AddIngredientsAmount> {
  String textValue;
  double _animatedContainerHeight=300;
  double _top=15;
  double _right=30;
  double _left=30;
  double _bottom=15;


  @override
  Widget build(BuildContext context) {

    void _toggleCardSize(){
      _top==15?_top=7.5: _top=15;
      _right==30?_right=7.5: _right=30;
      _left==30?_left=7.5: _left=30;
      _bottom==15?_bottom=7.5: _bottom=15;
    }

    void _toggleCardHeight(){
      _animatedContainerHeight==300?_animatedContainerHeight=500:_animatedContainerHeight=300;
    }
    return AnimatedPadding(
      duration: Duration(milliseconds: 500),
      curve: Curves.linearToEaseOut,
      padding:EdgeInsets.only(top: _top,right: _right,left: _left,bottom: _bottom),
      child: GestureDetector(
          onTap: (){
            setState(() {
              _toggleCardHeight();
              _toggleCardSize();
            });
          },
          child: AnimatedContainer(
              height:_animatedContainerHeight,
              duration: Duration(milliseconds: 500),
              child: Padding(
                padding: EdgeInsets.all(15.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    Container(
                      decoration: BoxDecoration(
                        border:Border.all(style: BorderStyle.solid, width: 1),
                        color: Colors.white,
                        borderRadius: BorderRadius.all(Radius.circular(90))),
                      child: Center(
                        child: Text("Malzemelerinizin Miktarını Belirlerin",style: TextStyle(
                          color: Colors.black,
                          fontFamily:'OpenSans',
                          fontSize:25,
                          fontWeight: FontWeight.w300,
                          ),
                        ),
                      ),
                    ),
                    SizedBox(height: 7.5,),
                    Expanded(
                      child: Container(
                        decoration: BoxDecoration(
                          color:Colors.white,
                          border: Border.all(style: BorderStyle.solid, width: 1),
                          borderRadius: BorderRadius.circular(10),
                        ),
                        child: ListView.builder(
                          itemCount: widget.selectedIngredients.length==null?0:
                            widget.selectedIngredients.length,
                          itemBuilder: (context, index){
                            return Padding(
                              padding: EdgeInsets.all(2),
                              child: Container(
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(90),
                                  border: Border.all(style:BorderStyle.solid,width: 1),
                                  color: Colors.white54,

                                ),
                                child: Row(
                                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                  crossAxisAlignment: CrossAxisAlignment.center,
                                  children: [
                                    Padding(
                                        padding: EdgeInsets.all(5),
                                        child: Text('${widget.selectedIngredients[index]}',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 30),)),
                                  ],
                                ),
                              ),
                            );
                          },
                        ),
                      ),
                    ),
                  ],
                ),
              ),
              decoration: BoxDecoration(
                border: Border.all(style: BorderStyle.solid, width: 1),
                borderRadius: BorderRadius.circular(30),
                color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
              )
          )
      ),
    );
  }
}

//------------------------------------------------------------------------

class AddRecipeVoice extends StatefulWidget {
  AddRecipeVoice({this.subCategoryId,this.subCategoryCardId});
  final int subCategoryCardId;
  final int subCategoryId;
  @override
  _AddRecipeVoiceState createState() => _AddRecipeVoiceState();
}
class _AddRecipeVoiceState extends State<AddRecipeVoice> {
  String textValue;

  @override
  Widget build(BuildContext context) {

    return AnimatedPadding(
      duration: Duration(seconds: 1),
      curve: Curves.linearToEaseOut,
      padding:EdgeInsets.only(top: 15,left: 30,right: 30,bottom: 7.5),
      child: GestureDetector(
          onTap: (){
            setState(() {
            });
          },
          child: Container(
              height:130,
              child: Padding(
                padding: EdgeInsets.all(15.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    Container(
                      decoration: BoxDecoration(
                          border:Border.all(style: BorderStyle.solid, width: 1),
                          color: Colors.white,
                          borderRadius: BorderRadius.all(Radius.circular(90))),
                      child: Center(
                        child: Text("Tarifinizi anlatın",style: TextStyle(
                          color: Colors.black,
                          fontFamily:'OpenSans',
                          fontSize:25,
                          fontWeight: FontWeight.w300,
                        ),
                        ),
                      ),
                    ),
                    SizedBox(height: 7.5,),
                    Expanded(
                      child: GestureDetector(
                        child: Container(
                          decoration: BoxDecoration(
                            color:kColorTheme7,
                            border: Border.all(style: BorderStyle.solid, width: 1),
                            borderRadius: BorderRadius.circular(20),
                          ),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.start,
                            children: [
                              Icon(Icons.mic,size: 40,color: Colors.white,),
                              SizedBox(width: 50,),
                              Text(
                                "KAYIT ZAMANI !!",
                                style: TextStyle(
                                  fontSize: 30,
                                  fontFamily: "OpenSans",
                                  color: Colors.white,
                                  fontWeight: FontWeight.bold
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
              decoration: BoxDecoration(
                border: Border.all(style: BorderStyle.solid, width: 1),
                borderRadius: BorderRadius.circular(30),
                color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
              )
          )
      ),
    );
  }
}

标签: androidiosflutter

解决方案


  1. 创建一个与 ChangeNotifier 混合的提供程序类。
  2. 在使用 MultiProvider 小部件调用提供程序类之前包装您的小部件。同样地:
    MultiProvider (
       providers: [
       ChangeNotifierProvider.value(value: IngredientsProvider()),
       ],
       child: YourWidget(), //You can wrap your MaterialApp here
    )
  1. 创建您需要的方法来更改所选数据并notifyListeners()在您的方法中调用。它将在您收听它们的地方重建您想要的小部件。

例子:

 class IngredientsProvider with ChangeNotifier {
    List<String> _selectedIngredients = [];
    
    List<String> get selectedIngredients() {
        return _selectedIngredients;
    }

    void addIngredient(String ingredient) {
        _selectedIngredients.add(ingredient);
        notifyListeners();
    }
}

在你的小部件中听他们:

   Widget1 {

   //Call this in you onPress/onTap
   void addIngredient(String ing, BuildContext ctx) {
        Provider.of<IngredientsProvider>(ctx, listen: 
        false).addIngredient(ing);
   }
   ........ 
   @override
   Widget build(BuildContext context) {
        //Use this list to select
        List<String> _ingredients = Provider.of<IngredientsProvider>(context, listen: 
        true).ingredients;
    }
   ........ 

}

这样在第二个Widget中使用。

   Widget2 {
   ........ 
   @override
   Widget build(BuildContext context) {
        //Use this list to show
        List<String> _ingredients = Provider.of<IngredientsProvider>(context, listen: 
        true).ingredients;

    }
   ........ 

}

推荐阅读