颤抖如何避免在将基于页面的数据添加到FutureBuilder时一次又一次地构建窗口小部件

时间:2020-04-27 05:56:23

标签: android flutter dart

我正在开发将来的构建器小部件,该小部件显示餐馆数据列表。因为列表很大,所以我有基于页面的数据,所以当Scroll控制器到达移动设备视图的末尾时,我会增加页面计数器。在这种情况下,我的api被调用了&数据正在追加,但是整个窗口小部件都重新构建了&不合适。下面是代码:


import 'package:flutter/material.dart';
import 'package:timeout_dubai/podo/RestaurantsData.dart';
import 'package:timeout_dubai/screens/ArticleDetails.dart';
import 'package:timeout_dubai/screens/BarsFliterScreen.dart';
import 'package:timeout_dubai/screens/TopPicsRestoScreen.dart';
import 'package:timeout_dubai/services/getRestaurantsData.dart';
import 'package:timeout_dubai/utils/RatingWidget.dart';
import 'package:timeout_dubai/constants/constants.dart' as Constants;

/*
* @author Sagar Chavan
* @since 14-feb-2020
* @version 1.0.0
* @class RestaurantFragment shows list of Restaurants
* */

class RastaurantsFragment extends StatefulWidget {
  RastaurantsFragment({Key key}) : super(key: key);

  @override
  RastaurantsFragmentState createState() => RastaurantsFragmentState();
}

class RastaurantsFragmentState extends State<RastaurantsFragment> {
  List data;
  final GetRestaurantsData httpService = GetRestaurantsData();

  var placeholder = "assets/images/placeholderimage.jpg";
  ScrollController _sc = new ScrollController();
  static int page = 0;
  static int tagid = 0;

  String toppickstext = "TIME OUT TOP PICKS";
  Future<List<RestaurantsData>> filteredrestodata;

  String SortType = "PUB_DATE";
  Future<List<RestaurantsData>> restodata;
  final GlobalKey<State> list1Key = new GlobalKey<State>();
  bool loadmore = false;

  @override
  void initState() {
    //getSortOption("PUB_DATE");
    restodata = httpService.getRestaurantsData(page, tagid, SortType, loadmore);

    // TODO: implement initState
    super.initState();

    _sc.addListener(() {
      if (_sc.position.pixels == _sc.position.maxScrollExtent) {
        loadmore = true;
        _getMoreData(page,loadmore);
      }
    });
  }

  Future<List<RestaurantsData>> _getMoreData(int index, bool loadmore) async {
    restodata = httpService.getRestaurantsData(index, tagid, SortType, loadmore);
    setState(() {
      //loadmore = loadmore;
      page++;
      restodata = httpService.getRestaurantsData(page, tagid, SortType, loadmore);

    });
  }

  goToArticleDetails(String nid, String image, String category, int rating) {
    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => ArticleDetails(nid, image, category, rating)));
  }

  getSortOption(String sortingtype) async {

    setState(() {
      SortType = sortingtype;
      restodata = httpService.getRestaurantsData(page, tagid, sortingtype, loadmore);
    });

  }

  @override
  void dispose() {
//    _bannerAd?.dispose();
//    _interstitialAd?.dispose();
    _sc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    print("RESTOLISTBUILD ${restodata.then((value) => print(value.length))}");


    return new Scaffold(
      body: FutureBuilder(
        future: restodata,
        builder: (BuildContext context,
            AsyncSnapshot<List<RestaurantsData>> snapshot) {
          print("DataTable:  ${snapshot.hasData}");
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          } else {
            if (snapshot.data?.isEmpty ?? true)
              return Center(
                  child: Text(
                'No data found',
                style: TextStyle(
                    color: Colors.black,
                    fontSize: 25,
                    fontWeight: FontWeight.w700),
              ));
            else
              List<RestaurantsData> posts = snapshot.data;
            //print("posts:  ${snapshot.data[index].template}");
            return NotificationListener<ScrollNotification>(
              // ignore: missing_return
              onNotification: (ScrollNotification scrollInfo) {
                if (scrollInfo.metrics.pixels ==
                    scrollInfo.metrics.maxScrollExtent) {
                  print("Scroll End");
                }
              },
              child: ListView.builder(
                  controller: _sc,
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Container(
                      padding: EdgeInsets.fromLTRB(0, 0, 0, 2),
                      child: GestureDetector(
                        child: Stack(
                          children: <Widget>[
                            ShaderMask(
                                shaderCallback: (rect) {
                                  return LinearGradient(
                                    begin: Alignment.topCenter,
                                    end: Alignment.bottomCenter,
                                    colors: [
                                      Constants.gradientStart,
                                      Constants.gradientEnd
                                    ],
                                  ).createShader(Rect.fromLTRB(
                                      0, 20, rect.width, rect.height - 20));
                                },
                                blendMode: BlendMode.darken,
                                child: Container(
                                  width: double.infinity,
                                  child: FadeInImage.assetNetwork(
                                    placeholder: placeholder,
                                    image: snapshot.data[index].image,
                                    fit: BoxFit.cover,
                                  ),
                                )),
                            if (snapshot.data[index].sponsored == 1)
                              Positioned(
                                  top: 20,
                                  left: 20,
                                  child: Container(
                                    padding: EdgeInsets.all(5),
                                    decoration: new BoxDecoration(
                                        border: new Border.all(
                                            width: 0,
                                            color: Colors
                                                .transparent), //color is transparent so that it does not blend with the actual color specified
                                        borderRadius: const BorderRadius.all(
                                            const Radius.circular(30.0)),
                                        color: Colors.black.withOpacity(
                                            0.4) // Specifies the background color and the opacity
                                        ),
                                    child: Text(
                                      "SPONSORED",
                                      style: TextStyle(color: Colors.white),
                                    ),
                                  )),
                            Positioned(
                              top: 20,
                              right: 20,
                              child: IconButton(
                                  icon: Icon(Icons.favorite, color:Colors.white ,),
                                  color: Colors.white
                                  //onPressed: () => removeFavourites(snapshot.data[index].nid),
                                  ),
                            ),
                            Positioned(
                              bottom: 20,
                              left: 20,
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: <Widget>[
                                  Container(
                                    width: 300,
                                    child: Text(
                                      "${snapshot.data[index].title}",
                                      softWrap: true,
                                      style: TextStyle(
                                        fontSize: 24,
                                        fontFamily: 'franklin-gothic-demi',
                                        fontWeight: FontWeight.bold,
                                        color: Color(0xffFFFFFF),
                                      ),
                                    ),
                                  ),
                                  Padding(
                                    padding: EdgeInsets.only(top: 5),
                                  ),
                                  if (snapshot.data[index].editor_rating !=
                                      null)
                                    RatingWidget(
                                        data:
                                            "${snapshot.data[index].editor_rating}"),
                                  Padding(
                                    padding: EdgeInsets.only(top: 5),
                                  ),
                                  if (snapshot
                                      .data[index].oarea_name.isNotEmpty)
                                    Row(
                                      children: <Widget>[
                                        Icon(
                                          Icons.location_on,
                                          color: Colors.white,
                                          size: 15,
                                        ),
                                        Text(
                                          "${snapshot.data[index].oarea_name}",
                                          style: TextStyle(
                                            fontSize: 18,
                                            fontFamily:
                                                'franklin-gothic-book-cnd.otf',
                                            color: Colors.white,
                                          ),
                                        ),
                                      ],
                                    ),
                                ],
                              ),
                            ),
                          ],
                        ),
                        onTap: () => goToArticleDetails(
                            "${snapshot.data[index].nid}",
                            snapshot.data[index].image,
                            "Restaurants",
                            snapshot.data[index].editor_rating,
                        ),
                      ),
                    );
                  }),
            ); // snapshot.data  :- get your object which is pass from your downloadData() function
          }
        },
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          FloatingActionButton(
            heroTag: "btn1",
            onPressed: () {
              Navigator.push(
                context,
                // Create the SelectionScreen in the next step.
                MaterialPageRoute(builder: (context) => BarsFilters()),
              );
            },
            child: Icon(
              Icons.filter_list,
              size: 30,
            ),
            backgroundColor: Color(0xff94C2D4),
            foregroundColor: Colors.white,
            elevation: 10,
            shape: RoundedRectangleBorder(
                borderRadius: new BorderRadius.circular(30.0),
                side: BorderSide(color: Colors.white)),
          ),
          SizedBox(
            width: 20,
          ),
          FloatingActionButton.extended(
            heroTag: "btn2",
            onPressed: () {
              _navigateAndDisplaySelection(context);
            },
            label: Text(
                "$toppickstext"
            ),
            backgroundColor: Color(0xff94C2D4),
            foregroundColor: Colors.white,
            elevation: 10,
            shape: RoundedRectangleBorder(
                borderRadius: new BorderRadius.circular(0.0),
                side: BorderSide(color: Colors.white)),
          ),
        ],
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }

  _navigateAndDisplaySelection(BuildContext context) async {
    // Navigator.push returns a Future that completes after calling
    // Navigator.pop on the Selection Screen.
    final result = await Navigator.push(
      context,
      // Create the SelectionScreen in the next step.
      MaterialPageRoute(builder: (context) => TopPicksRestoItems()),
    );
    if(result == null){
      setState(() {
        toppickstext = toppickstext;
        restodata = httpService.getRestaurantsData(page, 0, SortType, loadmore);
      });
    }else{
      setState(() {
        toppickstext = result["tagname"];
        restodata = httpService.getRestaurantsData(page, result["tagid"], SortType, loadmore);
      });
    }
  }
}

API调用类似于:

import 'dart:convert';
import 'package:http/http.dart';
import 'package:timeout_dubai/podo/BarsData.dart';
import 'package:timeout_dubai/podo/CategoriesList.dart';
import 'package:timeout_dubai/podo/RestaurantsData.dart';
/*
* @author Sagar Chavan
* @since 14-feb-2020
* @version 1.0.0
* @class GetRestaurantsData calls api to get restaurants section data
* */

class GetRestaurantsData {

  List<RestaurantsData> rsetata = new List();
  String sections;

  Future<List<RestaurantsData>> getRestaurantsData(int pageno, int tagid, String sortType, bool loadmore) async {

    if(tagid == 0){
      sections = '44';
    }else{
      sections = '0';

    }

    final uri = '';
    final headers = {'Content-Type': 'application/json'};
    Map<String, dynamic> body = {
      'site_key': 'timeoutdubai_en',
      'page': pageno,
      'sort': sortType,
      'sort_option': 'desc',
      'sections': '44',
      'tags': tagid,

    };
    String jsonBody = json.encode(body);
    final encoding = Encoding.getByName('utf-8');

    Response response = await post(
      uri,
      headers: headers,
      body: jsonBody,
      encoding: encoding,
    );

    Map<String, dynamic> map = jsonDecode(response.body);

    print('RESPONSEMAP: $map');

    List<dynamic> resbody = map["items"];
    print('RESPONSEBODY: $resbody');

    List<RestaurantsData> restaurantsobj = resbody
        .map(
          (dynamic item) => RestaurantsData.fromJson(item),
    )
        .toList();



    if(loadmore == true){
      rsetata.addAll(restaurantsobj);
    }else{
      rsetata = restaurantsobj;
    }

    print("RestorantdataCount ${rsetata.length}");


    return rsetata;
  }
}

0 个答案:

没有答案