gpt4 book ai didi

android - future 已经完成的 flutter 错误

转载 作者:IT王子 更新时间:2023-10-29 07:16:13 27 4
gpt4 key购买 nike

我无法找出“错误状态: future 已完成”的错误。我基本上有一个使用 BottomNavigationBar 的应用程序,并且在我的一个屏幕上我正在使用使用 Completer 类的此类。

再次创建 webview 时会发生这种情况:

      body: WebView(
initialUrl: 'https://www.google.com/',
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
)

第一个 View 中的所有内容都加载正常,但如果您选择另一个 BottomNavigationBarItem 然后返回类,我会收到错误状态异常: future 已经完成。以下是完整代码。

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:async';

class myClass extends StatelessWidget {
Completer<WebViewController> _controller = Completer<WebViewController>();
final Set<String> _favorites = Set<String>();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
NavigationControls(_controller.future),
Menu(_controller.future, () => _favorites),
],
),
//EXCEPTION OCCURS HERE
//BAD STATE: FUTURE ALREADY COMPLETED
body: WebView(
initialUrl: 'https://www.google.com/',
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
),
floatingActionButton: _bookmarkButton(),
);
}

_bookmarkButton() {
return FutureBuilder<WebViewController>(
future: _controller.future,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> controller) {
if (controller.hasData) {
return FloatingActionButton(
onPressed: () async {
var url = await controller.data.currentUrl();
_favorites.add(url);
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Saved $url for later reading.')),
);
},
child: Icon(Icons.favorite),
);
}
return Container();
},
);
}
}

class Menu extends StatelessWidget {
Menu(this._webViewControllerFuture, this.favoritesAccessor);
final Future<WebViewController> _webViewControllerFuture;
final Function favoritesAccessor;

@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _webViewControllerFuture,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> controller) {
if (!controller.hasData) return Container();
return PopupMenuButton<String>(
onSelected: (String value) async {
if (value == 'Email link') {
var url = await controller.data.currentUrl();
await launch(
'mailto:?subject=hello&body=$url');
} else {
var newUrl = await Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return FavoritesPage(favoritesAccessor());
}));
Scaffold.of(context).removeCurrentSnackBar();
if (newUrl != null) controller.data.loadUrl(newUrl);
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
const PopupMenuItem<String>(
value: 'Email link',
child: Text('Email link'),
),
const PopupMenuItem<String>(
value: 'See Favorites',
child: Text('See Favorites'),
),
],
);
},
);
}
}

class FavoritesPage extends StatelessWidget {
FavoritesPage(this.favorites);
final Set<String> favorites;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Favorite pages')),
body: ListView(
children: favorites
.map((url) => ListTile(
title: Text(url), onTap: () => Navigator.pop(context, url)))
.toList()),
);
}
}

class NavigationControls extends StatelessWidget {
const NavigationControls(this._webViewControllerFuture)
: assert(_webViewControllerFuture != null);
final Future<WebViewController> _webViewControllerFuture;
@override
Widget build(BuildContext context) {
return FutureBuilder<WebViewController>(
future: _webViewControllerFuture,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
final bool webViewReady =
snapshot.connectionState == ConnectionState.done;
final WebViewController controller = snapshot.data;
return Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: !webViewReady
? null
: () => navigate(context, controller, goBack: true),
),
IconButton(
icon: const Icon(Icons.arrow_forward_ios),
onPressed: !webViewReady
? null
: () => navigate(context, controller, goBack: false),
),
],
);
},
);
}

navigate(BuildContext context, WebViewController controller,
{bool goBack: false}) async {
bool canNavigate =
goBack ? await controller.canGoBack() : await controller.canGoForward();
if (canNavigate) {
goBack ? controller.goBack() : controller.goForward();
} else {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text("No ${goBack ? 'back' : 'forward'} history item")),
);
}
}
}

最佳答案

试图重现问题,但未能成功。你能用你的底部导航栏等显示代码吗?我是这样解释的,在这里它起作用了:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: "/",
routes: {
"/": (context) => Home(),
},
);
}
}

class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
final navigatorKey = GlobalKey<NavigatorState>();
int _currentIndex = 0;
final pagesRouteFactories = {
'page1': (RouteSettings settings) => MaterialPageRoute<dynamic>(
builder: (BuildContext context) => HomePage(),
settings: settings,
),
'page2': (RouteSettings settings) => MaterialPageRoute<dynamic>(
builder: (BuildContext context) => MyClass(),
settings: settings,
),
};

@override
Widget build(BuildContext context) {
return Scaffold(
body: MaterialApp(
navigatorKey: navigatorKey,
onGenerateRoute: (RouteSettings route) =>
pagesRouteFactories[route.name](route),
initialRoute: 'page1',
),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.white,
type: BottomNavigationBarType.fixed,
currentIndex: _currentIndex,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: FittedBox(
child: Text(
'Home',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
BottomNavigationBarItem(
icon: Icon(Icons.web),
title: FittedBox(
child: Text(
'Web',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
),
],
onTap: (int index) {
setState(() {
_currentIndex = index;
});
navigatorKey.currentState
.pushReplacementNamed(pagesRouteFactories.keys.toList()[index]);
},
),
);
}
}

class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Text('hi'),
),
);
}
}

class MyClass extends StatelessWidget {
Completer<WebViewController> _controller = Completer<WebViewController>();
final Set<String> _favorites = Set<String>();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
NavigationControls(_controller.future),
Menu(_controller.future, () => _favorites),
],
),
//EXCEPTION OCCURS HERE
//BAD STATE: FUTURE ALREADY COMPLETED
body: WebView(
initialUrl: 'https://www.google.com/',
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
),
floatingActionButton: _bookmarkButton(),
);
}

_bookmarkButton() {
return FutureBuilder<WebViewController>(
future: _controller.future,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> controller) {
if (controller.hasData) {
return FloatingActionButton(
onPressed: () async {
var url = await controller.data.currentUrl();
_favorites.add(url);
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Saved $url for later reading.')),
);
},
child: Icon(Icons.favorite),
);
}
return Container();
},
);
}
}

class Menu extends StatelessWidget {
Menu(this._webViewControllerFuture, this.favoritesAccessor);
final Future<WebViewController> _webViewControllerFuture;
final Function favoritesAccessor;

@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _webViewControllerFuture,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> controller) {
if (!controller.hasData) return Container();
return PopupMenuButton<String>(
onSelected: (String value) async {
if (value == 'Email link') {
var url = await controller.data.currentUrl();
await launch('mailto:?subject=hello&body=$url');
} else {
var newUrl = await Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return FavoritesPage(favoritesAccessor());
}));
Scaffold.of(context).removeCurrentSnackBar();
if (newUrl != null) controller.data.loadUrl(newUrl);
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
const PopupMenuItem<String>(
value: 'Email link',
child: Text('Email link'),
),
const PopupMenuItem<String>(
value: 'See Favorites',
child: Text('See Favorites'),
),
],
);
},
);
}
}

class FavoritesPage extends StatelessWidget {
FavoritesPage(this.favorites);
final Set<String> favorites;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Favorite pages')),
body: ListView(
children: favorites
.map((url) => ListTile(
title: Text(url), onTap: () => Navigator.pop(context, url)))
.toList()),
);
}
}

class NavigationControls extends StatelessWidget {
const NavigationControls(this._webViewControllerFuture)
: assert(_webViewControllerFuture != null);
final Future<WebViewController> _webViewControllerFuture;
@override
Widget build(BuildContext context) {
return FutureBuilder<WebViewController>(
future: _webViewControllerFuture,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
final bool webViewReady =
snapshot.connectionState == ConnectionState.done;
final WebViewController controller = snapshot.data;
return Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: !webViewReady
? null
: () => navigate(context, controller, goBack: true),
),
IconButton(
icon: const Icon(Icons.arrow_forward_ios),
onPressed: !webViewReady
? null
: () => navigate(context, controller, goBack: false),
),
],
);
},
);
}

navigate(BuildContext context, WebViewController controller,
{bool goBack: false}) async {
bool canNavigate =
goBack ? await controller.canGoBack() : await controller.canGoForward();
if (canNavigate) {
goBack ? controller.goBack() : controller.goForward();
} else {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text("No ${goBack ? 'back' : 'forward'} history item")),
);
}
}
}


关于android - future 已经完成的 flutter 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57326704/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com