我正在开发将来的构建器小部件,该小部件显示餐馆数据列表。因为列表很大,所以我有基于页面的数据,所以当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;
}
}