当滚动视图到达尾端时,我试图更新模型的列表,虽然我能够这样做,但我无法顺利地完成它。我希望每当用户到达滚动卷的中间时,将新图像从API加载到模型列表中,这样滚动就会像在当前场景中一样平稳,当用户到达末尾时,会有一两秒钟的暂停,然后添加新元素,这样用户就不会知道是否添加了新的元素。另外,我目前的方法是在主线程上增加太多的负载,并使应用程序崩溃。
下面的代码如下:
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);
}
}
顶部列表视图仅用于类别,可以忽略。网格view.builder具有核心功能
发布于 2020-10-18 03:53:45
虽然我无法解决主要问题(每次滚动到屏幕中部时加载,这样用户就不必等待并查看进度条),但是我能够解决所有其他问题。
main.dart
import 'package:flutter/material.dart';
import 'package:wallpaper_app/data/provider_data.dart';
import 'package:wallpaper_app/screens/home.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context)=>ProviderData(),
child: MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: Colors.black,
),
title: 'Wallpaper App',
home: Home()
),
);
}
}
home.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wallpaper_app/data/data.dart';
import 'package:wallpaper_app/data/provider_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';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart';
import 'package:flutter_pagewise/flutter_pagewise.dart';
Data data = Data();
List<CategoriesModel> categories;
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
void initState() {
// TODO: implement initState
super.initState();
categories = data.getCategories();
WidgetsBinding.instance.addPostFrameCallback((_) async {
_controller = ScrollController();
_controller.addListener(() {
if (_controller.position.atEdge) {
if (_controller.position.pixels == 0)
print('top');
// you are at top position
else{
print('end');
// incrementIndex();
if(Provider.of<ProviderData>(context,listen: false).pageIndex>5){
print('image cache: ${imageCache.currentSize}');
imageCache.clear();
}
Provider.of<ProviderData>(context,listen: false).incrementPage();
getWallpapers(Provider.of<ProviderData>(context,listen: false).pageIndex);
}
// you are at bottom position
}
});
getWallpapers(Provider.of<ProviderData>(context,listen: false).pageIndex);
});
}
ScrollController _controller;
void getWallpapers(var index) async {
if(!Provider.of<ProviderData>(context,listen: false).isPerformingRequest){
Provider.of<ProviderData>(context,listen: false).togglePerformingRequest();
try {
Network network = Network();
Map<String, dynamic> jsonData = await network.getCuratedWallpapers(
index, 80);
jsonData["photos"].forEach((element) {
WallpaperModel wallpaperModel = WallpaperModel.fromMap(element);
setState(() {
Provider.of<ProviderData>(context,listen: false).addWallpapers(wallpaperModel);
});
});
}
catch(e){
print(e);
}
Provider.of<ProviderData>(context,listen: false).togglePerformingRequest();
}
}
@override
Widget build(BuildContext context) {
SystemChrome.setEnabledSystemUIOverlays([]);
return Scaffold(
// appBar: AppBar(
// backgroundColor: Colors.black,
// 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,
// ),
Expanded(
// padding: EdgeInsets.symmetric(horizontal: 10),
child: GridView.builder(
controller: _controller,
physics: ScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 6.0,
mainAxisSpacing: 6.0,
childAspectRatio: 0.6),
addAutomaticKeepAlives: false,
itemBuilder: (context,index){
if(index==(Provider.of<ProviderData>(context,listen: false).wallpapers!=null?Provider.of<ProviderData>(context,listen: false).wallpapers.length+0:80)){
return _buildProgressIndicator();
}
else
return WallpaperTile(small: Provider.of<ProviderData>(context,listen: false).wallpapers[index].src.medium,);
},
itemCount: Provider.of<ProviderData>(context,listen: false).wallpapers!=null?Provider.of<ProviderData>(context,listen: false).wallpapers.length+1:81,
),
)
],
),
),
// ),
);
}
}
Widget _buildProgressIndicator() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: 1,
child: new CircularProgressIndicator(),
),
),
);
}
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;
String medium;
SrcModel({this.original, this.small, this.portrait,this.medium});
factory SrcModel.fromMap(Map<String, dynamic> jsonData) {
return SrcModel(
original: jsonData["original"],
small: jsonData["small"],
medium: jsonData["medium"],
portrait: jsonData["portrait"]);
}
}
network.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
const apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
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,
});
print(response.statusCode);
// print(response.body);
return jsonDecode(response.body);
}
}
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(
margin: EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.grey
),
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child:
Image.network(
small,
fit: BoxFit.cover,
cacheHeight: 400,
cacheWidth: 225,
)
),
);
}
}
provider_data.dart
import 'package:flutter/foundation.dart';
import 'package:wallpaper_app/model/wallpaper_model.dart';
class ProviderData extends ChangeNotifier{
List<WallpaperModel> wallpapers =[];
bool isPerformingRequest = false;
var pageIndex=1;
void togglePerformingRequest(){
isPerformingRequest = !isPerformingRequest;
notifyListeners();
}
void incrementPage(){
pageIndex++;
print(pageIndex);
notifyListeners();
}
void addWallpapers(WallpaperModel wallpaperModel){
wallpapers.add(wallpaperModel);
notifyListeners();
}
}
发布于 2020-10-17 18:00:51
您需要将NotificationListener
与ScrollNotification
结合使用。用您的需求来修改它。
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int present = 0;
int perPage = 15;
final originalItems = List<String>.generate(10000, (i) => "Item $i");
var items = List<String>();
@override
void initState() {
super.initState();
setState(() {
items.addAll(originalItems.getRange(present, present + perPage));
present = present + perPage;
});
}
void loadMore() {
setState(() {
if((present + perPage )> originalItems.length) {
items.addAll(
originalItems.getRange(present, originalItems.length));
} else {
items.addAll(
originalItems.getRange(present, present + perPage));
}
present = present + perPage;
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo.metrics.pixels ==
scrollInfo.metrics.maxScrollExtent / 2) {
loadMore();
}
},
child: ListView.builder(
itemCount: (present <= originalItems.length) ? items.length + 1 : items.length,
itemBuilder: (context, index) {
return (index == items.length ) ?
Container(
color: Colors.greenAccent,
child: FlatButton(
child: Text("Load More"),
onPressed: () {
loadMore();
},
),
)
:
ListTile(
title: Text('${items[index]}'),
);
},
),
),
);
}
}
读更多。
发布于 2022-09-19 12:24:47
在您的GridView.builder中尝试SliverGrid而不是home.dart
。
因为当您使用GridView.builder
时,它将同时加载所有可能的结果,而不是使用SliverGrid
时,它将只加载当前存在于screen
中的数据。
SliverGrid(delegate: SliverChildBuilderDelegate((context, int index) {
final _wallpaper = wallpaper.photos ? [index];
return Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10.0),), height: MediaQuery
.of(context)
.size
.height / 2, child: GestureDetector(onTap: () {
//Wallpaper Preview
},
child: Hero(tag: '${_wallpaper?.id}',
child: ClipRRect(borderRadius: BorderRadius.circular(10.0),
child: CachedNetworkImage(fit: BoxFit.cover,
imageUrl: _wallpaper!.src!.large!,
filterQuality: FilterQuality.high,
progressIndicatorBuilder: (context, url, progress) => Center(child: CircularProgressIndicator()),),),),),);
}, childCount: wallpaper.photos?.length),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 0.5, crossAxisSpacing: 5.0 mainAxisSpacing: 5.0,),),
注意:去掉你不需要的额外的。
https://stackoverflow.com/questions/64405266
复制相似问题