Listview 仅在我热重载或刷新后显示
Listview is showing only after I hot reload or refresh in flutter
我几乎什么都试过了。我的函数异步,我的快照异步。我正在使用未来的建设者,我的旋转木马滑块工作正常。我不需要热重载或刷新轮播滑块。但是对于我的列表视图构建器,我需要每次都刷新以获取数据。我尝试了 if 语句的连接状态状态,但连接状态很快就完成了(在数据完全加载之前)。所以我的图片和数据不会在没有刷新或热重载的情况下出现。
import 'package:cached_network_image/cached_network_image.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:video_games/model.dart';
import 'package:flutter/material.dart';
import 'package:video_games/send_models.dart';
import 'package:video_games/views/details_view.dart';
import 'package:get/get.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
class HomePage extends StatefulWidget {
HomePage({
Key? key,
}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future<Autogenerated> apiCall() async {
final response = await http.get(Uri.parse(
'https://api.rawg.io/api/games?key=5ac29048d12d45d0949c77038115cb56&page=1'));
return Autogenerated.fromJson(jsonDecode(response.body));
}
int slideractiveindex = 0;
var urlImages = [];
var uniqueImages = [];
var growableList = [];
var listId = [];
@override
Widget build(BuildContext context) {
clearCache();
return SingleChildScrollView(
child: Column(
children: [
FutureBuilder<Autogenerated>(
future: apiCall(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
List<Results>? data = snapshot.data!.results;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CarouselSlider.builder(
itemCount: 20,
itemBuilder: (context, index, realIndex) {
urlImages.add(data![index].backgroundImage);
uniqueImages = urlImages.toSet().toList();
final urlImage = uniqueImages[index];
return buildImage(urlImage, index);
},
options: CarouselOptions(
autoPlay: true,
enlargeCenterPage: true,
onPageChanged: (index, reason) {}),
),
const SizedBox(height: 32),
],
);
},
),
FutureBuilder<Autogenerated>(
future: apiCall(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
print(snapshot.connectionState);
print(urlImages.length);
List<Results>? data = snapshot.data!.results;
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, index) {
growableList.add(data![index].name);
listId.assign(data[index].id);
// String? id = data[index].id.toString();
// urlImages.add(data[index].backgroundImage);
uniqueImages = urlImages.toSet().toList();
final urlImage = uniqueImages[index + 1];
return Padding(
padding: const EdgeInsets.all(10.0),
child: ListTile(
tileColor: Colors.black12,
leading: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsPage(
id: '${data[index].id}',
),
));
},
child: buildImage2(urlImage, index)),
title: Column(
children: [
Text(
'${data[index].name}',
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Rating : ${data[index].rating}'),
SizedBox(
width: 20,
),
Text('Release : ${data[index].released}'),
],
)
],
),
),
);
},
itemCount: 19,
);
} else {
return CircularProgressIndicator();
}
},
),
],
),
);
}
Widget buildImage(String? urlImage, int index) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 12),
color: Colors.grey,
child: CachedNetworkImage(
imageUrl: urlImage!,
fit: BoxFit.cover,
key: UniqueKey(),
errorWidget: (context, url, error) => Icon(Icons.error),
placeholder: (context, url) => Container(
child: Center(
child: CircularProgressIndicator(),
),
),
));
}
Widget buildImage2(String? urlImage, int index) {
return Container(
height: 100,
width: 100,
child: CachedNetworkImage(
imageUrl: urlImage!,
key: UniqueKey(),
fit: BoxFit.cover,
errorWidget: (context, url, error) => Icon(Icons.error),
placeholder: (context, url) => Container(
child: Center(
child: CircularProgressIndicator(),
),
),
));
}
void clearCache() {
DefaultCacheManager().emptyCache();
imageCache!.clear();
imageCache!.clearLiveImages();
setState(() {});
}
}
这是我的错误部分
════════ Exception caught by widgets library ═══════════════════════════════════
RangeError (index): Invalid value: Valid value range is empty: 17
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════
RangeError (index): Invalid value: Valid value range is empty: 18
════════════════════════════════════════════════════════════════════════════════
FutureBuilder
删除样板代码。 see
假设您想在页面启动时从后端获取一些数据并显示加载程序直到数据到来。
ListBuilder 的任务:
有两个状态变量,dataFromBackend
和isLoadingFlag On
启动,设置isLoadingFlag = true
,并以此为基础,显示loader
.
数据到达后,使用从后端获取的数据设置数据并设置
isLoadingFlag = false
(显然在 setState
内)
我们需要 if-else
创建小部件。如果 isLoadingFlag
是
true
,显示 loader
,否则显示 data
。失败时,显示错误
消息。
FutureBuilder 的任务:
- 在Future Builder
future
中给出异步任务
- 基于
connectionState
,显示消息(加载中,active(streams)
,
done
)
- 基于
data(snapshot.hasError)
,显示视图
FutureBuilder 的优点
- 不使用两个状态变量和setState
- 响应式编程(FutureBuilder 将负责更新
查看数据到达)
示例:
FutureBuilder<String>(
future: _fetchNetworkCall, // async work
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting: return Text('Loading....');
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else
return Text('Result: ${snapshot.data}');
}
},
)
我几乎什么都试过了。我的函数异步,我的快照异步。我正在使用未来的建设者,我的旋转木马滑块工作正常。我不需要热重载或刷新轮播滑块。但是对于我的列表视图构建器,我需要每次都刷新以获取数据。我尝试了 if 语句的连接状态状态,但连接状态很快就完成了(在数据完全加载之前)。所以我的图片和数据不会在没有刷新或热重载的情况下出现。
import 'package:cached_network_image/cached_network_image.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:video_games/model.dart';
import 'package:flutter/material.dart';
import 'package:video_games/send_models.dart';
import 'package:video_games/views/details_view.dart';
import 'package:get/get.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
class HomePage extends StatefulWidget {
HomePage({
Key? key,
}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future<Autogenerated> apiCall() async {
final response = await http.get(Uri.parse(
'https://api.rawg.io/api/games?key=5ac29048d12d45d0949c77038115cb56&page=1'));
return Autogenerated.fromJson(jsonDecode(response.body));
}
int slideractiveindex = 0;
var urlImages = [];
var uniqueImages = [];
var growableList = [];
var listId = [];
@override
Widget build(BuildContext context) {
clearCache();
return SingleChildScrollView(
child: Column(
children: [
FutureBuilder<Autogenerated>(
future: apiCall(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
List<Results>? data = snapshot.data!.results;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CarouselSlider.builder(
itemCount: 20,
itemBuilder: (context, index, realIndex) {
urlImages.add(data![index].backgroundImage);
uniqueImages = urlImages.toSet().toList();
final urlImage = uniqueImages[index];
return buildImage(urlImage, index);
},
options: CarouselOptions(
autoPlay: true,
enlargeCenterPage: true,
onPageChanged: (index, reason) {}),
),
const SizedBox(height: 32),
],
);
},
),
FutureBuilder<Autogenerated>(
future: apiCall(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
print(snapshot.connectionState);
print(urlImages.length);
List<Results>? data = snapshot.data!.results;
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, index) {
growableList.add(data![index].name);
listId.assign(data[index].id);
// String? id = data[index].id.toString();
// urlImages.add(data[index].backgroundImage);
uniqueImages = urlImages.toSet().toList();
final urlImage = uniqueImages[index + 1];
return Padding(
padding: const EdgeInsets.all(10.0),
child: ListTile(
tileColor: Colors.black12,
leading: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsPage(
id: '${data[index].id}',
),
));
},
child: buildImage2(urlImage, index)),
title: Column(
children: [
Text(
'${data[index].name}',
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Rating : ${data[index].rating}'),
SizedBox(
width: 20,
),
Text('Release : ${data[index].released}'),
],
)
],
),
),
);
},
itemCount: 19,
);
} else {
return CircularProgressIndicator();
}
},
),
],
),
);
}
Widget buildImage(String? urlImage, int index) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 12),
color: Colors.grey,
child: CachedNetworkImage(
imageUrl: urlImage!,
fit: BoxFit.cover,
key: UniqueKey(),
errorWidget: (context, url, error) => Icon(Icons.error),
placeholder: (context, url) => Container(
child: Center(
child: CircularProgressIndicator(),
),
),
));
}
Widget buildImage2(String? urlImage, int index) {
return Container(
height: 100,
width: 100,
child: CachedNetworkImage(
imageUrl: urlImage!,
key: UniqueKey(),
fit: BoxFit.cover,
errorWidget: (context, url, error) => Icon(Icons.error),
placeholder: (context, url) => Container(
child: Center(
child: CircularProgressIndicator(),
),
),
));
}
void clearCache() {
DefaultCacheManager().emptyCache();
imageCache!.clear();
imageCache!.clearLiveImages();
setState(() {});
}
}
这是我的错误部分
════════ Exception caught by widgets library ═══════════════════════════════════
RangeError (index): Invalid value: Valid value range is empty: 17
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════
RangeError (index): Invalid value: Valid value range is empty: 18
════════════════════════════════════════════════════════════════════════════════
FutureBuilder
删除样板代码。 see
假设您想在页面启动时从后端获取一些数据并显示加载程序直到数据到来。
ListBuilder 的任务:
有两个状态变量,
dataFromBackend
和isLoadingFlag On
启动,设置
isLoadingFlag = true
,并以此为基础,显示loader
.数据到达后,使用从后端获取的数据设置数据并设置
isLoadingFlag = false
(显然在setState
内)我们需要
if-else
创建小部件。如果isLoadingFlag
是true
,显示loader
,否则显示data
。失败时,显示错误 消息。
FutureBuilder 的任务:
- 在Future Builder
future
中给出异步任务 - 基于
connectionState
,显示消息(加载中,active(streams)
,done
) - 基于
data(snapshot.hasError)
,显示视图
FutureBuilder 的优点
- 不使用两个状态变量和setState
- 响应式编程(FutureBuilder 将负责更新 查看数据到达)
示例:
FutureBuilder<String>(
future: _fetchNetworkCall, // async work
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting: return Text('Loading....');
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else
return Text('Result: ${snapshot.data}');
}
},
)