flutter - 未来建造者在 CustomScrollView 内部颤动
问题描述
嗨,我想设计一个应该垂直滚动并且应该有 GridView.builder 的页面。我正在访问服务器以加载数据,如果数据处于共享首选项中,那么我将从共享首选项中获取它。对于 GridView.builder,我使用 FutureBuilder 加载数据。但我收到以下错误是错误
'owner._debugCurrentBuildTarget == this':不是真的
下面是代码。
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Initialize without device test ids
Admob.initialize();
// Add a list of test ids.
// Admob.initialize(testDeviceIds: ['YOUR DEVICE ID']);
runApp(FirstScreen());
}
class FirstScreen extends StatefulWidget {
@override
_CrosspromoPageState createState() => _CrosspromoPageState();
}
class _CrosspromoPageState extends State<FirstScreen> {
AdmobInterstitial interstitialAd;
List<CrosspromotionPojo> crosspromoobject = List();
@override
void initState() {
// TODO: implement initState
super.initState();
// getCrosspromodata();
// loadcrossPromodata();
interstitialAd = AdmobInterstitial(
adUnitId: getInterstitialAdUnitId(),
listener: (AdmobAdEvent event, Map<String, dynamic> args) {
if (event == AdmobAdEvent.closed) interstitialAd.load();
},
);
interstitialAd.load();
}
String getInterstitialAdUnitId() {
if (Platform.isIOS) {
return 'ca-app-pub-3940256099942544/4411468910';
} else if (Platform.isAndroid) {
return 'ca-app-pub-3940256099942544/1033173712';
}
return null;
}
@override
Widget build(BuildContext context) {
SizeConfig().init(context);
SizeConfig().init(context);
return Scaffold(
body: Container(
child: CustomScrollView(
slivers: <Widget>[
new Image.asset('assets/images/bg_half_image.jpg'),
new Align(
alignment: Alignment.topCenter,
child: new Container(
margin: EdgeInsets.fromLTRB(0, 55, 0, 0),
width: 150,
height: 150,
child: Image.asset('assets/images/logo.png'),
)),
new Align(
alignment: Alignment.topCenter,
child: InkWell(
onTap: () async {
if (await interstitialAd.isLoaded) {
interstitialAd.show();
}
int val = await DatabaseHelper.instance.queryRowCount();
if (val == 0) {
DatabaseHelper.instance.insertExcdaydata();
DatabaseHelper.instance.insertExcdaydatainapp();
} else
Navigator.pop(context, true);
{
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BannerPage(),
),
);
}
},
child: new Container(
width: 150,
margin: EdgeInsets.fromLTRB(0, 200, 0, 0),
//padding: EdgeInsets.fromLTRB(4, 0, 4, 4),
child: new Image.asset('assets/images/start.png'),
))),
new Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(
left: 0,
right: 0,
top: SizeConfig.screenHeight / 1.8,
bottom: 0),
child: Text("TRY OUR NEW APPS",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20)),
),
new FutureBuilder<dynamic>(
future: getCrosspromodata(),
builder:
(BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text('Please wait its loading...'));
} else {
return Container(
margin: EdgeInsets.only(
left: 0,
right: 0,
top: SizeConfig.screenHeight / 1.6,
bottom: 0),
child: Align(
child: GridView.builder(
itemCount: crosspromoobject.length,
itemBuilder: (context, index) => GestureDetector(
onTap: () => tapped(index),
child: Container(
child: new Card(
elevation: 2,
child: Column(
children: <Widget>[
new Container(
child: CachedNetworkImage(
imageUrl: crosspromoobject[index].appUrl,
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
new Container(
alignment:
AlignmentDirectional.centerStart,
child: Text(
crosspromoobject[index].app_name,
style: TextStyle(
color: Colors.black, fontSize: 15),
))
],
),
)),
),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 30,
crossAxisSpacing: 15,
childAspectRatio:
MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.1),
),
),
),
);
}
})
],
),
),
);
/*return Scaffold(
body: Scaffold(
body: Stack(
children: [
new Image.asset('assets/images/bg_half_image.jpg'),
new Align(
alignment: Alignment.topCenter,
child: new Container(
margin: EdgeInsets.fromLTRB(0, 55, 0, 0),
width: 150,
height: 150,
child: Image.asset('assets/images/logo.png'),
)),
new Align(
alignment: Alignment.topCenter,
child: InkWell(
onTap: () async {
if (await interstitialAd.isLoaded) {
interstitialAd.show();
}
int val = await DatabaseHelper.instance.queryRowCount();
if (val == 0) {
DatabaseHelper.instance.insertExcdaydata();
DatabaseHelper.instance.insertExcdaydatainapp();
} else
Navigator.pop(context, true);
{
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BannerPage(),
),
);
}
},
child: new Container(
width: 150,
margin: EdgeInsets.fromLTRB(0, 200, 0, 0),
//padding: EdgeInsets.fromLTRB(4, 0, 4, 4),
child: new Image.asset('assets/images/start.png'),
))),
new Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(
left: 0, right: 0, top: SizeConfig.screenHeight / 1.8, bottom: 0),
child: Text("TRY OUR NEW APPS",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20)),
),
new FutureBuilder<dynamic>(
future: getCrosspromodata(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text('Please wait its loading...'));
} else {
return Container(
margin: EdgeInsets.only(
left: 0,
right: 0,
top: SizeConfig.screenHeight / 1.6,
bottom: 0),
child: Align(
child: GridView.builder(
itemCount: crosspromoobject.length,
itemBuilder: (context, index) => GestureDetector(
onTap: () => tapped(index),
child: Container(
child: new Card(
elevation: 2,
child: Column(
children: <Widget>[
new Container(
child: CachedNetworkImage(
imageUrl: crosspromoobject[index].appUrl,
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
new Container(
alignment: AlignmentDirectional.centerStart,
child: Text(
crosspromoobject[index].app_name,
style: TextStyle(
color: Colors.black, fontSize: 15),
))
],
),
)),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 30,
crossAxisSpacing: 15,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.1),
),
),
),
);
}
})
],
)))*/
}
Future<dynamic> loadcrossPromodata() async {
SharedPreferences pref = await SharedPreferences.getInstance();
List<dynamic> tagObjsJson =
(json.decode(pref.getString('userData')) ?? List<dynamic>());
crosspromoobject = tagObjsJson
.map((tagJson) => CrosspromotionPojo.fromJson(tagJson))
.toList();
return tagObjsJson;
}
Future<dynamic> getCrosspromodata() async {
List<dynamic> tagObjsJson;
SharedPreferences pref = await SharedPreferences.getInstance();
try {
Response<Map> versionresponse = await Dio().get(
"https://videomergerapp.com/mobilestores/https/cross_promo_photoapps/verison.json");
Map arrayObjresponse = versionresponse.data;
int version = arrayObjresponse['healthw_version'];
int localversion = pref.getInt('local_version') ?? 0;
if (version > localversion) {
Response<Map> response = await Dio().get(
"https://videomergerapp.com/mobilestores/https/cross_promo_fitness/cross_promo_health_fitness_firstscreen.json");
String arrayObjsText = response.toString();
tagObjsJson = jsonDecode(arrayObjsText)['item_array'] as List;
crosspromoobject = tagObjsJson
.map((tagJson) => CrosspromotionPojo.fromJson(tagJson))
.toList();
savePojo(tagObjsJson);
pref.setInt('local_version', version);
return tagObjsJson;
} else {
loadcrossPromodata();
}
} catch (e) {
print(e);
}
}
Future<void> savePojo(List<dynamic> crosspromoobject) async {
SharedPreferences pref = await SharedPreferences.getInstance();
pref.setString('userData', json.encode(crosspromoobject));
print(crosspromoobject);
}
void tapped(int index) {
Fluttertoast.showToast(
msg: crosspromoobject[index].app_name,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
}
解决方案
所以我通过在 CustomScrollView 中获取 SliverList 和 SliverChildListDelegate 并为 FutureBuilder 中的容器高度赋予高度:SizeConfig.screenHeight / 1.10,下面是完整代码。
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Initialize without device test ids
Admob.initialize();
// Add a list of test ids.
// Admob.initialize(testDeviceIds: ['YOUR DEVICE ID']);
runApp(FirstScreen());
}
class FirstScreen extends StatefulWidget {
@override
_CrosspromoPageState createState() => _CrosspromoPageState();
}
class _CrosspromoPageState extends State<FirstScreen> {
AdmobInterstitial interstitialAd;
List<CrosspromotionPojo> crosspromoobject = List();
@override
void initState() {
// TODO: implement initState
super.initState();
// getCrosspromodata();
// loadcrossPromodata();
}
@override
Widget build(BuildContext context) {
SizeConfig().init(context);
SizeConfig().init(context);
return Scaffold(
body: Container(
child: CustomScrollView(slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate(
[
Stack(
children: [
new Image.asset('assets/images/bg_half_image.jpg'),
new Align(
alignment: Alignment.topCenter,
child: new Container(
margin: EdgeInsets.fromLTRB(0, 55, 0, 0),
width: 150,
height: 150,
child: Image.asset('assets/images/logo.png'),
)),
new Align(
alignment: Alignment.topCenter,
child: InkWell(
onTap: () async {
if (await interstitialAd.isLoaded) {
interstitialAd.show();
}
int val = await DatabaseHelper.instance.queryRowCount();
if (val == 0) {
DatabaseHelper.instance.insertExcdaydata();
DatabaseHelper.instance.insertExcdaydatainapp();
} else
Navigator.pop(context, true);
{
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BannerPage(),
),
);
}
},
child: new Container(
width: 150,
margin: EdgeInsets.fromLTRB(0, 200, 0, 0),
//padding: EdgeInsets.fromLTRB(4, 0, 4, 4),
child: new Image.asset('assets/images/start.png'),
)))
],
),
new SizedBox(
height: 50,
width: double.infinity,
child: Container(
margin: EdgeInsets.fromLTRB(0, 15, 0, 0),
color: Colors.white,
child: Text(
"TRY OUR NEW APPS",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20),
),
),
),
new FutureBuilder<dynamic>(
future: getCrosspromodata(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text('Please wait its loading...'));
} else {
return Container(
height: SizeConfig.screenHeight / 1.10,
margin:
EdgeInsets.only(left: 0, right: 0, top: 0, bottom: 0),
child: Align(
child: GridView.builder(
itemCount: crosspromoobject.length,
itemBuilder: (context, index) => GestureDetector(
onTap: () => tapped(index),
child: Container(
child: new Card(
elevation: 2,
child: Column(
children: <Widget>[
new Container(
child: CachedNetworkImage(
imageUrl: crosspromoobject[index].appUrl,
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
new Container(
alignment: AlignmentDirectional.centerStart,
child: Text(
crosspromoobject[index].app_name,
style: TextStyle(
color: Colors.black, fontSize: 15),
))
],
),
)),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 30,
crossAxisSpacing: 15,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.1),
),
),
),
);
}
})
],
)),
]))
// This trailing comma makes auto-formatting nicer for build methods.
);
}
Future<String> loadcrossPromodata() async {
SharedPreferences pref = await SharedPreferences.getInstance();
List<dynamic> tagObjsJson =
(json.decode(pref.getString('userData')) ?? List<dynamic>());
crosspromoobject = tagObjsJson
.map((tagJson) => CrosspromotionPojo.fromJson(tagJson))
.toList();
}
Future<dynamic> getCrosspromodata() async {
List<dynamic> tagObjsJson;
SharedPreferences pref = await SharedPreferences.getInstance();
try {
Response<Map> versionresponse = await Dio().get(
"https://videomergerapp.com/mobilestores/https/cross_promo_photoapps/verison.json");
Map arrayObjresponse = versionresponse.data;
int version = arrayObjresponse['healthw_version'];
int localversion = pref.getInt('local_version') ?? 0;
if (version > localversion) {
Response<Map> response = await Dio().get(
"https://videomergerapp.com/mobilestores/https/cross_promo_fitness/cross_promo_health_fitness_firstscreen.json");
String arrayObjsText = response.toString();
tagObjsJson = jsonDecode(arrayObjsText)['item_array'] as List;
crosspromoobject = tagObjsJson
.map((tagJson) => CrosspromotionPojo.fromJson(tagJson))
.toList();
savePojo(tagObjsJson);
pref.setInt('local_version', version);
return tagObjsJson;
} else {
loadcrossPromodata();
}
} catch (e) {
print(e);
}
}
Future<void> savePojo(List<dynamic> crosspromoobject) async {
SharedPreferences pref = await SharedPreferences.getInstance();
pref.setString('userData', json.encode(crosspromoobject));
print(crosspromoobject);
}
void tapped(int index) {
Fluttertoast.showToast(
msg: crosspromoobject[index].app_name,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
}
推荐阅读
- angular - Jasmine - 测试一个具有参数功能的方法
- java - 是否可以用另一个字符串中的字符替换字符串中的字符?
- reactjs - React Router 传递信息
- python-3.x - 尝试安装支持 GPU 的 LightGBM
- elasticsearch - ELK 堆栈中 Django 的正确 Grok 解析器?
- garmin - 为什么字体没有像 API 中描述的那样覆盖整个设备屏幕?
- boto3 - 气流中的 S3Hook:没有属性“get_credentials”
- forms - CakePHP 3 在控件表单中使用关联数据时无法发出标头
- git - Revert To This Revision 和... To Parent 之间有什么区别
- jquery - 在 create-react-app 中包含其他外部库的 jQuery