繁体   English   中英

如何在导航抽屉中更新有状态的小部件,同时在Android中保留像片段一样的类?

[英]How to update stateful widget in Navigation drawer while keeping same class like fragments in Android?

我想更新类的有状态小部件,同时从服务器,导航抽屉中获取数据后返回同一个类。 我遇到的问题是该类仅加载一次数据,如果我导航到导航抽屉的另一项,则保持不变。 因为状态仅创建一次。

这是我的代码:

class CategoryFilter extends StatefulWidget {
 int productIndex;
 String category_name;
 CategoryFilter(this.productIndex, this.category_name)
 {
  print("CategoryFilter");
  print(productIndex);
  print(category_name);
  new _CategoryFilterState(productIndex, category_name);
}

 @override
 _CategoryFilterState createState() => new 
_CategoryFilterState(productIndex, category_name);
}

 class _CategoryFilterState extends State<CategoryFilter> {

 int productIndex;
 List<ResponseDataProducts> productList;
 List data;
 String category_name;

_CategoryFilterState(this.productIndex, this.category_name)
 {
   print("CategoryFilter");
   print(productIndex);
  print(category_name);
}

@override
void initState(){
super.initState();

    Future<String> status = getData(productIndex);

    status.then((onValue){

    if(onValue.toString() == "Success")
    {

      Navigator.pop(context);

    }

  });


  // this.getData();
 }

 @override
 Widget build(BuildContext context) {
  return new Scaffold(

    body: new Container(
        color: Colors.white30,

        child: new ListView.builder(
           itemCount: productList == null ? 0 : productList.length,
           itemBuilder: (BuildContext context, int index) {

             return new Container(

               margin: const EdgeInsets.only( bottom: 10.0),
               constraints: new BoxConstraints.expand(
                  height: 200.0

               ),
               alignment: Alignment.bottomLeft,

               decoration: new BoxDecoration(
                   image: new DecorationImage(image:
                   new NetworkImage
                     ("http://myurl.com/"+productList[index].thumbnail),
                      fit: BoxFit.cover)
               ),
               child:new Container(

                 child: new Text(
                   productList[index].name,
                   style: new TextStyle(color: Colors.white, fontSize: 30.0),
                 ),
                color: Colors.black54,
                 alignment: new FractionalOffset(0.5, 0.0),
                 height: 35.0,
                 // margin: const EdgeInsets.symmetric(vertical: 30.0),

               ),
             );
            })
    ),
  ) ;
}



  void _onLoading()
  {
    showDialog(context: context,
       barrierDismissible: false,
      child: progress);

    new Future.delayed(new Duration(seconds: 2), (){
    // Navigator.pop(context);
   });

  }


   Future<String> getData(int productIndex) async {
   productList = new List<ResponseDataProducts>();


     _onLoading();

   http.Response response = await http.get(
       Uri.encodeFull(CommonMethods.base_url + 'product/$productIndex'),
    headers: {"Accept": "application/json"});

print(response.body);

  setState(() {
    var convertDataToJson = JSON.decode(response.body);
    data = convertDataToJson["responseData"];
    for(int i=0; i<data.length; i++)
  {

    ResponseDataProducts responseData = new ResponseDataProducts(
        data[i]["id"],
        data[i]["name"], data[i]["description"],
        data[i]["title"], data[i]["thumbnail"]);
    productList.add(responseData);
  }
  //Navigator.pop(context);

});

return "Success";
}
 }

这是我从导航抽屉中调用categoryFilter类的方式:

_getDraserItemWidget(int pos)
 {
  switch(pos)
  {
  case 0:

    return new Home(bar_id);


  case 1:



    return  new CategoryFilter(categoryList[pos-1].id, categoryList[pos-1].name);



  case 2:



  return  new CategoryFilter(categoryList[pos-1].id, categoryList[pos-1].name);


  case 3:


    return  new CategoryFilter(categoryList[pos-1].id, categoryList[pos-1].name);


  case 4:

    return new OpeningTime();


  case 5:

    break;



 }
 }

我建议您使用FutureBuilder小部件,而不是调用该方法在类的initState方法内加载数据。 如果从导航抽屉返回一个新的FutureBuilder ,则每次创建一个新的FutureBuilder都应该调用您的服务,这通常是执行异步请求的更好方法。

这是一个非常简单的示例。 它不能很好地完成抽屉操作(或其他一些事情-只能花很多时间在这样的事情上),但是它应该可以说明这个概念。

请注意,与其“更新小部件”,不如说只是创建一个新的小部件。 由于颤动的执行方式,因此它应该相对来说性能较高,尤其是因为您并非一直在执行此操作,而是仅在用户从导航菜单中选择某个内容时才这样做。

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new MyAppState();
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new TextPage(text: "Home!"),
    );
  }
}

Map<int, int> _nums = Map();

class TextPage extends StatelessWidget {
  final String text;

  const TextPage({Key key, @required this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new PreferredSize(
        child: new Container(),
        preferredSize: Size.fromHeight(10.0),
      ),
      body: new Center(
        child: new Text(text),
      ),
      drawer: new Builder(
        builder: (context) => Material(
              child: new SafeArea(
                child: Column(
                  children: <Widget>[
                    new FlatButton(
                      onPressed: () {
                        Navigator.pushReplacement(
                            context, new MaterialPageRoute(builder: (context) => _getDrawerItemWidget(1)));
                      },
                      child: Text("First item"),
                    ),
                    new FlatButton(
                      onPressed: () {
                        Navigator.pushReplacement(
                            context, new MaterialPageRoute(builder: (context) => _getDrawerItemWidget(2)));
                      },
                      child: Text("Second item"),
                    ),
                  ],
                ),
              ),
            ),
      ),
    );
  }

  _getDrawerItemWidget(int i) {
    return new FutureBuilder<String>(
      builder: (context, AsyncSnapshot<String> snapshot) {
        if (snapshot.data != null) {
          return new TextPage(text: snapshot.data);
        } else {
          return new TextPage(text: "Loading.");
        }
      },
      future: () async {
        var num = _nums.putIfAbsent(i, () => 0);
        _nums[i] = num + 1;
        String toReturn = "You retrieved number $i for the $num time";
        return await Future.delayed<String>(Duration(seconds: 1), () => toReturn);
      }(),
    );
  }
}

从理论上讲,您可以在保留GlobalKey引用并使用它们调用子小部件上的方法(如果它与当前选择匹配,以使其进行更新)上做一些不同的操作,但这通常是一个不好的主意-最佳做法鼓励您向下传递数据到小部件树,而不是向下调用函数。 如果必须使用GlobalKeys,通常可以重构以做得更好。

暂无
暂无

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

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