I am trying to update the list of the models when the scroll view reaches the end, while I was able to do so, I am unable to do it smoothly. I want to load the new images from the API into the List of models whenever the user reaches the middle of the scroll so that the scrolling feels smooth as in the current scenario, there is a second or two of pause when the user hits the end after which the new elements will be added so the user won't know if the new elements are added. Also, my current approach is putting too much load on the main thread and is crashing the app.
here's the code below:
home.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wallpaper_app/data/data.dart';
import 'package:wallpaper_app/model/categories.dart';
import 'package:wallpaper_app/model/wallpaper_model.dart';
import 'package:wallpaper_app/network/network.dart';
import 'package:wallpaper_app/widgets/branding.dart';
import 'package:wallpaper_app/widgets/list_tile.dart';
import 'package:wallpaper_app/widgets/wallpaper_tile.dart';
var pageIndex=1;
Data data = Data();
List<CategoriesModel> categories;
List<WallpaperModel> wallpapers =[];
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
void initState() {
// TODO: implement initState
super.initState();
_controller = ScrollController();
_controller.addListener(() {
if (_controller.position.atEdge) {
if (_controller.position.pixels == 0)
print('top');
// you are at top position
else{
print('end');
incrementIndex();
getWallpapers(pageIndex);
}
// you are at bottom position
}
});
categories = data.getCategories();
getWallpapers(pageIndex);
}
ScrollController _controller;
void incrementIndex(){
setState(() {
pageIndex++;
});
}
void getWallpapers(var index) async {
try {
Network network = Network();
Map<String, dynamic> jsonData = await network.getCuratedWallpapers(
index, 80);
jsonData["photos"].forEach((element) {
WallpaperModel wallpaperModel = WallpaperModel.fromMap(element);
setState(() {
wallpapers.add(wallpaperModel);
});
// for (var wallpaper in wallpapers){
// print(wallpaper.src.small);
// }
});
}
catch(e){
print(e);
}
}
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: Color(0xff999999), // navigation bar color
));
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
title: Brand(),
),
body: SingleChildScrollView(
controller: _controller,
child: Container(
child: Column(
children: [
Container(
height: 100,
child: ListView.builder(
// controller: _controller,
padding: EdgeInsets.all(10),
itemCount: categories.length,
// shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return CategoriesTile(
imageUrl: categories[index].imageUrl,
title: categories[index].categoriesName,
);
}),
),
SizedBox(
height: 20,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: GridView.builder(
physics: ScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 6.0,
mainAxisSpacing: 6.0,
childAspectRatio: 0.6),
itemBuilder: (context,index){
// if(index==50){
//// incrementIndex();
// getWallpapers(pageIndex+1);
// }
return WallpaperTile(small: wallpapers[index].src.portrait,);
},
itemCount: wallpapers.length,
),
)
],
),
),
),
);
}
}
wallpaper_model.dart
class WallpaperModel {
String photographer;
String photographerUrl;
int photographerId;
SrcModel src;
WallpaperModel(
{this.photographer, this.photographerUrl, this.photographerId, this.src});
factory WallpaperModel.fromMap(Map<String,dynamic> jsonData){
return WallpaperModel(
photographer: jsonData["photographer"],
photographerId: jsonData["photographer_id"],
photographerUrl: jsonData["photographer_url"],
src: SrcModel.fromMap(jsonData["src"])
);
}
}
class SrcModel {
String original;
String small;
String portrait;
SrcModel({this.original, this.small, this.portrait});
factory SrcModel.fromMap(Map<String, dynamic> jsonData) {
return SrcModel(
original: jsonData["original"],
small: jsonData["small"],
portrait: jsonData["portrait"]);
}
}
wallpaper_tile.dart
import 'package:flutter/material.dart';
class WallpaperTile extends StatelessWidget {
final String small;
WallpaperTile({this.small});
@override
Widget build(BuildContext context) {
return Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child:
Image.network(
small,
fit: BoxFit.cover,
)),
);
}
}
network.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
const apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
class Network{
Future<dynamic> getCuratedWallpapers(var pageNo, var maxWallpapers) async{
var response = await http.get("https://api.pexels.com/v1/curated/?page=$pageNo&per_page=$maxWallpapers",
headers: {
"Authorization":apiKey
});
return jsonDecode(response.body);
}
}
the top list view is just for categories and can be ignored. it's the grid view.builder that has the core functionality