I am getting the following error when beginning to implement the camera plugin on my flutter app:
[VERBOSE-2:dart_error.cc(16)] Unhandled exception:
MissingPluginException(No implementation found for method init on channel plugins.flutter.io/camera)
#0 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:153:7)
<asynchronous suspension>
#1 _channel (package:camera/camera.dart:7:5)
#2 _channel (package:camera/camera.dart:6:21)
#3 availableCameras (package:camera/camera.dart:42:41)
<asynchronous suspension>
#4 main (file:///Users/waynerumble/Desktop/scott_and_viki/lib/main.dart:10:19)
<asynchronous suspension>
#5 _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:279:19)
#6 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:165:12)
[VERBOSE-2:dart_error.cc(16)] Unhandled exception:
MissingPluginException(No implementation found for method list on channel plugins.flutter.io/camera)
#0 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:153:7)
<asynchronous suspension>
#1 availableCameras (package:camera/camera.dart:42:50)
<asynchronous suspension>
#2 main (file:///Users/waynerumble/Desktop/scott_and_viki/lib/main.dart:10:19)
<asynchronous suspension>
#3 _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:279:19)
#4 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:165:12)
The error doesn't occur until i start using the plugin itself, i.e. if i replace Future<null> main() etc with void main() => runApp(new App()); the app runs fine. I've followed install instructions from the link provided and tried pasting in all the example incode in place of mine but still get the errors
My main.dart:
import 'package:flutter/material.dart';
import 'Localisations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'dart:async';
import 'package:camera/camera.dart';
List<CameraDescription> cameras;
Future<Null> main() async {
cameras = await availableCameras();
runApp(new App());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var statusBarHeight = MediaQuery.of(context).padding.top;
var titleText = new Text(Localize.of(context).appTitle,
textAlign: TextAlign.center,
style: new TextStyle(fontFamily: 'CallingAngelsPersonalUse',
fontSize: 50.0,
color: Colors.black)
);
var backgroundImage = new BoxDecoration(
image: new DecorationImage(
image: new AssetImage('assets/background.png'),
fit: BoxFit.cover,
),
);
var mainContainer = new Container(
padding: EdgeInsets.only(top: statusBarHeight),
height: double.infinity,
width: double.infinity,
decoration: backgroundImage,
child: new Column(
children: <Widget>[
new Container(
margin: EdgeInsets.only(top: 10.0),
child: titleText
)
],
),
);
return new Scaffold(
body: mainContainer,
);
}
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
onGenerateTitle: (BuildContext context) => Localize.of(context).appTitle,
localizationsDelegates: [
const LocalizeDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', '')
],
home: new MyApp(),
);
}
}
My pubspec.yml:
dependencies:
flutter:
sdk: flutter
camera: ^0.1.2
path_provider: ^0.4.0
flutter_localizations:
sdk: flutter
This is my first real flutter app so any help would be appreciated.
Thanks
first check your app.build minSdkVersion.make sure minSdkVersion is 21.
minSdkVersion 21
here code example.
List<CameraDescription> cameras = [];
main() async{
WidgetsFlutterBinding.ensureInitialized();
try {
cameras = await availableCameras();
} on CameraException catch (e) {
logError(e.code, e.description);
}
runApp(MyApp());
}
Related
I want to go to Second Page with Navigator.push method. So I am using ElevatedButton Widget for this purpose. I'm also using Statefull Widget. My source code like in below:
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'ScannerPage.dart';
void main() {
runApp(const QrCodeMainWindow());
}
class QrCodeMainWindow extends StatefulWidget {
const QrCodeMainWindow({Key? key}) : super(key: key);
#override
State<QrCodeMainWindow> createState() => _QrCodeMainWindowState();
}
class _QrCodeMainWindowState extends State<QrCodeMainWindow> {
final String _data = "";
QRViewController? controller;
Barcode? result;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
#override
Widget build(BuildContext context) {
final ButtonStyle style = ElevatedButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('QR Code Scanner App'),
backgroundColor: Colors.blueAccent,
),
body: Column(
children: [
ElevatedButton(
child: Text('Scan'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ScannerPage()),
);
}),
Text(_data)
],
),
),
);
}
When I run this App succesfuly openning on simulator (Iphone 13). But when I press the button I get below error.
How Can I solve this error ?
======== Exception caught by gesture ===============================================================
The following assertion was thrown while handling a gesture:
Navigator operation requested with a context that does not include a Navigator.
The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
When the exception was thrown, this was the stack:
#0 Navigator.of.<anonymous closure> (package:flutter/src/widgets/navigator.dart:2553:9)
#1 Navigator.of (package:flutter/src/widgets/navigator.dart:2560:6)
#2 Navigator.push (package:flutter/src/widgets/navigator.dart:2016:22)
#3 _QrCodeMainWindowState.build.<anonymous closure> (package:qr_code_scanner_example/main.dart:51:29)
#4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:989:21)
#5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:198:24)
#6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:608:11)
#7 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:296:5)
#8 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:230:7)
#9 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:563:9)
#10 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:94:12)
#11 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:139:9)
#12 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:539:8)
#13 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:137:18)
#14 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:123:7)
#15 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:439:19)
#16 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:419:22)
#17 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:322:11)
#18 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:374:7)
#19 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:338:5)
#20 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:296:7)
#21 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:279:7)
#25 _invoke1 (dart:ui/hooks.dart:170:10)
#26 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:331:7)
#27 _dispatchPointerDataPacket (dart:ui/hooks.dart:94:31)
(elided 3 frames from dart:async)
Handler: "onTap"
Recognizer: TapGestureRecognizer#ba4ae
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(46.3, 135.7)
finalLocalPosition: Offset(46.3, 26.7)
button: 1
sent tap down
I trying to add a Drop down inside a Row.
When I do this
Row(
children: <Widget>[
Expanded(child:TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Terms',
hintText: '%'
),
)),
Expanded(child:DropdownButton<String>(
items:_currencies.map((String value){
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value : 'Rupee',
)),
],
)
Im getting a error
erforming hot reload...
Syncing files to device iPhone XR...
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown building SIForm(dirty, state: _SIFormState#da46e):
flutter: 'package:flutter/src/material/dropdown.dart': Failed assertion: line 560 pos 15: 'items == null ||
flutter: items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value ==
flutter: value).length == 1': is not true.
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter: https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #2 new DropdownButton (package:flutter/src/material/dropdown.dart:560:15)
flutter: #3 _SIFormState.build (package:simple_cal/main.dart:65:31)
flutter: #4 StatefulElement.build (package:flutter/src/widgets/framework.dart:3825:27)
flutter: #5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3736:15)
flutter: #6 Element.rebuild (package:flutter/src/widgets/framework.dart:3559:5)
flutter: #7 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2273:33)
flutter: #8 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:700:20)
flutter: #9 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:268:5)
flutter: #10 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:988:15)
flutter: #11 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:928:9)
flutter: #12 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:749:7)
flutter: #14 _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
flutter: #15 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
flutter: #16 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
flutter: (elided 3 frames from class _AssertionError and package dart:async)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
Reloaded 1 of 432 libraries in 736ms.
Here is my full main.dart file
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
Widget MyApp() {
return MaterialApp(
title: 'Simple Intrest app',
home: SIForm (),
);
}
class SIForm extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _SIFormState ();
}
}
class _SIFormState extends State<SIForm>{
var _currencies = ["Rupees","USD","CAD"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Simple Interest Calc"),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top : 5.0,bottom : 5.0),
child: TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'principle',
hintText: 'Enter the principle amout'
),
)),
Padding(
padding: EdgeInsets.only(top : 5.00*2,bottom : 5.00*2),
child : TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Rate of Interest',
hintText: '%'
),
)),
Row(
children: <Widget>[
Expanded(child:TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Terms',
hintText: '%'
),
)),
Expanded(child:DropdownButton<String>(
items:_currencies.map((String value){
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value : 'Rupee',
)),
],
)
],
),
),
);
}
}
documentation of DropdownButton says
value: 'Rupees'
not
value: 'Rupee'
because
var _currencies = ["Rupees","USD","CAD"];
and you have to add
onChanged: (str){},
Change from value to "Rupees" and add onChanged function
DropdownButton<String>(
items:_currencies.map((String value){
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value : 'Rupees',
onChanged: (val){},),
I'm trying to follow the Computer Vision with ML Kit - Flutter In Focus tutorial, where I followed the tutorial step-by step, and still didn't manage to make it work.
my code is as follow:
import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:async';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_ml_vision/firebase_ml_vision.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,
),
home: FacePage(),
);
}
}
class FacePage extends StatefulWidget{
#override
createState() => _FacePageState();
}
class _FacePageState extends State<FacePage>{
File _imageFile;
List<Face> _faces;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Face Detector'),
),
body: ImageAndFaces(),
floatingActionButton: FloatingActionButton(
onPressed: _getImageAndDetectFace,
tooltip: 'Pick an Image',
child: Icon(Icons.add_a_photo),
),
);
}
void _getImageAndDetectFace() async {
final imageFile = await ImagePicker.pickImage(
source: ImageSource.gallery,
);
final image = FirebaseVisionImage.fromFile(imageFile);
final faceDetector = FirebaseVision.instance.faceDetector(
FaceDetectorOptions(
mode: FaceDetectorMode.accurate,
enableLandmarks: true,
),
);
List<Face> faces = await faceDetector.detectInImage(image);
if(mounted) {
setState(() {
_imageFile = imageFile;
_faces = faces;
});
}
}
}
class ImageAndFaces extends StatelessWidget {
ImageAndFaces({this.imageFile, this.faces});
final File imageFile;
final List<Face> faces;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Flexible(
flex: 2 ,
child: Container(
constraints: BoxConstraints.expand(),
child: Image.file(imageFile, fit: BoxFit.cover),
),
),
Flexible(flex: 1 ,
child: ListView(
children: faces.map<Widget>((f) => FaceCoordinates(f)).toList(),
),
),
],
);
}
}
class FaceCoordinates extends StatelessWidget {
FaceCoordinates(this.face);
final Face face;
#override
Widget build(BuildContext context) {
final pos = face.boundingBox;
return ListTile(
title: Text('(${pos.top}, ${pos.left}, ${pos.bottom}, ${pos.right})'),
);
}
}
I'm getting the following exception stack:
I/flutter ( 5077): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 5077): The following assertion was thrown building ImageAndFaces(dirty):
I/flutter ( 5077): 'package:flutter/src/painting/image_provider.dart': Failed assertion: line 532 pos 14: 'file !=
I/flutter ( 5077): null': is not true.
I/flutter ( 5077):
I/flutter ( 5077): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter ( 5077): more information in this error message to help you determine and fix the underlying cause.
I/flutter ( 5077): In either case, please report this assertion by filing a bug on GitHub:
I/flutter ( 5077): https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter ( 5077):
I/flutter ( 5077): When the exception was thrown, this was the stack:
I/flutter ( 5077): #2 new FileImage (package:flutter/src/painting/image_provider.dart:532:14)
I/flutter ( 5077): #3 new Image.file (package:flutter/src/widgets/image.dart:254:16)
I/flutter ( 5077): #4 ImageAndFaces.build (package:visionappwork/main.dart:94:28)
I/flutter ( 5077): #5 StatelessElement.build (package:flutter/src/widgets/framework.dart:3789:28)
I/flutter ( 5077): #6 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3736:15)
.........
Does anybody know what the problem is?
I tried anything I can think of, including trying to catch the 'ImageAndFaces' class constructor as it creates an instance, without any success.
I'm new to flutter and dart, so maybe it's a stupid mistake.
Thanks a lot!
The reason you're having a problem is that imageFile starts out null. Since it's being passed in to Image.file(imageFile, fit: BoxFit.cover) you're seeing the failure due to the assertion that the file passed to Image.file is not null.
You need to add some logic to check whether imageFile is null and do something different if it is.
I am trying to test a custom widget GoogleSignInButton.
Here is the implementation of the widget:
import 'package:flutter/material.dart';
class GoogleSignInButton extends StatelessWidget {
GoogleSignInButton({this.onPressed});
final Function onPressed;
#override
Widget build(BuildContext context) {
Image _buildLogo() {
return Image.asset(
"assets/g-logo.png",
height: 18.0,
width: 18.0,
);
}
Opacity _buildText() {
return Opacity(
opacity: 0.54,
child: Text(
"Sign in with Google",
style: TextStyle(
fontFamily: 'Roboto-Medium',
color: Colors.black,
),
),
);
}
return MaterialButton(
height: 40.0,
onPressed: this.onPressed,
color: Colors.white,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_buildLogo(),
SizedBox(width: 24.0),
_buildText(),
],
),
);
}
}
I am trying to test the onPressed function callback by the test that follows.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import '../lib/ui/widgets/google_sign_in_button.dart';
void main() {
testWidgets('my first widget test', (WidgetTester tester) async {
var pressed = false;
var widget = GoogleSignInButton(
onPressed: () => () {
pressed = true;
},
);
await tester.pumpWidget(
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return MaterialApp(
home: Material(
child: Center(
child: widget,
),
),
);
},
),
);
await tester.press(find.byWidget(widget));
expect(pressed, equals(true));
});
}
Unfortunately, the test fails.
I am executing my widget test on the command line by flutter test test/widget_test.dart and here is the result of the test:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Expected: <true>
Actual: <false>
When the exception was thrown, this was the stack:
#4 main.<anonymous closure> (file:///home/hans/Development/flutter/recipes_app/test/widget_test.dart:30:5)
<asynchronous suspension>
#5 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:72:23)
#6 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:566:19)
<asynchronous suspension>
#9 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:550:14)
#10 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:893:24)
#16 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:890:15)
#17 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:71:22)
#18 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:27)
<asynchronous suspension>
#19 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:249:15)
<asynchronous suspension>
#24 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:246:5)
#25 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:166:33)
#30 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:165:13)
<asynchronous suspension>
#31 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:399:25)
<asynchronous suspension>
#45 _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
#46 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
#47 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
(elided 28 frames from class _FakeAsync, package dart:async, and package stack_trace)
This was caught by the test expectation on the following line:
file:///home/hans/Development/flutter/recipes_app/test/widget_test.dart line 30
The test description was:
my first widget test
════════════════════════════════════════════════════════════════════════════════════════════════════
00:01 +0 -1: my first widget test [E]
Test failed. See exception logs above.
The test description was: my first widget test
00:02 +0 -1: Some tests failed.
Any ideas why the test fails?
Your closure is wrong:
() => () {
pressed = true;
},
You need to write it either like that
() {
pressed = true;
},
Or like that
() => ( pressed = true )
And you need to trigger the tester.tap method.
That's my working code:
var pressed = false;
var widget = GoogleSignInButton(
onPressed: () {
pressed = true;
debugPrint("Pressed!");
},
);
await tester.pumpWidget(
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return MaterialApp(
home: Material(
child: Center(
child: widget,
),
),
);
},
),
);
expect(find.byWidget(widget), findsOneWidget);
await tester.tap(find.byWidget(widget));
expect(pressed, isTrue);
And I've supposed that when you run your project your Widget renders well and does not throw any errors.
HINT: make a flutter clean after any change in your test_file.dart change.
I'm not sure if the initState is the right function for this.
What I'm trying to achieve is to check when the page is rendered to perform some checks and based on them opening a AlertDialog to make some settings if needed.
I've got a Page which has a state.
It's initState function looks like this:
#override
void initState() {
super.initState();
if (!_checkConfiguration()) {
_showConfiguration(context);
}
}
The _showConfiguration like this:
void _showConfiguration(BuildContext context) {
AlertDialog dialog = new AlertDialog(
content: new Column(
children: <Widget>[
new Text('#todo')
],
),
actions: <Widget>[
new FlatButton(onPressed: (){
Navigator.pop(context);
}, child: new Text('OK')),
],
);
showDialog(context: context, child: dialog);
}
If there's a better way to make this checks and if needed call the modal, please point me in the proper direction, I was looking for a onState or onRender function, or a callback I could assign to the build function to be called on render but wasn't able to find one.
Edit: It seams over here they had a similar problem: Flutter Redirect to a page on initState
The member variable context can be accessed during initState but can't be used for everything. This is from the flutter for initState documentation:
You cannot use [BuildContext.inheritFromWidgetOfExactType] from this
method. However, [didChangeDependencies] will be called immediately
following this method, and [BuildContext.inheritFromWidgetOfExactType]
can be used there.
You could move your initialization logic to didChangeDependencies, however that might not be exactly what you want as didChangeDependencies can be called multiple times in the lifecycle of the widget.
If you instead make an asynchronous call which delegates your call until after the widget has been initialized, you can then use context as you intend.
A simple way to do that is to use a future.
Future.delayed(Duration.zero,() {
... showDialog(context, ....)
});
Another way, which may be more 'correct', is to use flutter's scheduler to add a post-frame callback:
SchedulerBinding.instance.addPostFrameCallback((_) {
... showDialog(context, ....)
});
And finally, here's a little trick I like to do to use asynchronous calls in the initState function:
() async {
await Future.delayed(Duration.zero);
... showDialog(context, ...)
}();
Here's a fully fleshed out example using the simple Future.delayed:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
bool _checkConfiguration() => true;
void initState() {
super.initState();
if (_checkConfiguration()) {
Future.delayed(Duration.zero,() {
showDialog(context: context, builder: (context) => AlertDialog(
content: Column(
children: <Widget>[
Text('#todo')
],
),
actions: <Widget>[
FlatButton(onPressed: (){
Navigator.pop(context);
}, child: Text('OK')),
],
));
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
);
}
}
With more context from the OP provided in comments, I can give a slightly better solution to their specific problem. Depending on the app, you may actually want to make a decision based on which page to show depending on whether it's the first time the app is opened i.e. set home to something different. And dialogs aren't necessarily the best UI element on mobile; it may be better to show a full page with the settings they need to add and a next button.
Wrapping with Future
#override
void initState() {
super.initState();
_store = Store();
new Future.delayed(Duration.zero,() {
_store.fetchContent(context);
});
}
====== UPDATED ======
Just like pointed by Lucas Rueda ( thanks to him :), When we need to get context inside initState() in order to work with "Provider", we should set the parameter listen to be = false. It makes sense because we should not listen to the initState() phase. So, for example, it should be:
final settingData = Provider.of<SettingProvider>(context, listen: false);
=========== OLD ANSWER =======
Most examples of initState() in this thread may be works for "UI" things such as "Dialog" which is the case in the root question of this thread.
But unfortunately, it doesn't work for me when applying it to get context for "Provider".
Hence, I pick didChangeDependencies() approach. As mentioned in the accepted answer, it has a caveat which is, it can be called multiple times in the lifecycle of the widget. However, it quite easy to handle it. Just use a single helper variable which is bool to prevent multiple calls inside didChangeDependencies(). Here is the example usage of _BookListState class with variable _isInitialized as the main "stopper" of "multiple calls":
class _BookListState extends State<BookList> {
List<BookListModel> _bookList;
String _apiHost;
bool _isInitialized; //This is the key
bool _isFetching;
#override
void didChangeDependencies() {
final settingData = Provider.of<SettingProvider>(context);
this._apiHost = settingData.setting.apiHost;
final bookListData = Provider.of<BookListProvider>(context);
this._bookList = bookListData.list;
this._isFetching = bookListData.isFetching;
if (this._isInitialized == null || !this._isInitialized) {// Only execute once
bookListData.fetchList(context);
this._isInitialized = true; // Set this to true to prevent next execution using "if()" at this root block
}
super.didChangeDependencies();
}
...
}
Here is error logs when I am trying to do initState() approach:
E/flutter ( 3556): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: 'package:provider/src/provider.dart': Failed assertion: line 242 pos 7: 'context.owner.debugBuilding ||
E/flutter ( 3556): listen == false ||
E/flutter ( 3556): debugIsInInheritedProviderUpdate': Tried to listen to a value exposed with provider, from outside of the widget tree.
E/flutter ( 3556):
E/flutter ( 3556): This is likely caused by an event handler (like a button's onPressed) that called
E/flutter ( 3556): Provider.of without passing `listen: false`.
E/flutter ( 3556):
E/flutter ( 3556): To fix, write:
E/flutter ( 3556): Provider.of<SettingProvider>(context, listen: false);
E/flutter ( 3556):
E/flutter ( 3556): It is unsupported because may pointlessly rebuild the widget associated to the
E/flutter ( 3556): event handler, when the widget tree doesn't care about the value.
E/flutter ( 3556):
E/flutter ( 3556): The context used was: BookList(dependencies: [_InheritedProviderScope<BookListProvider>], state: _BookListState#1008f)
E/flutter ( 3556):
E/flutter ( 3556): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39)
E/flutter ( 3556): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
E/flutter ( 3556): #2 Provider.of
package:provider/src/provider.dart:242
E/flutter ( 3556): #3 _BookListState.initState.<anonymous closure>
package:perpus/…/home/book-list.dart:24
E/flutter ( 3556): #4 new Future.delayed.<anonymous closure> (dart:async/future.dart:326:39)
E/flutter ( 3556): #5 _rootRun (dart:async/zone.dart:1182:47)
E/flutter ( 3556): #6 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter ( 3556): #7 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter ( 3556): #8 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
E/flutter ( 3556): #9 _rootRun (dart:async/zone.dart:1190:13)
E/flutter ( 3556): #10 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter ( 3556): #11 _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1021:23)
E/flutter ( 3556): #12 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
E/flutter ( 3556): #13 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
E/flutter ( 3556): #14 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
E/flutter ( 3556): #15 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
E/flutter ( 3556):
Simple use Timer.run()
#override
void initState() {
super.initState();
Timer.run(() {
// you have a valid context here
});
}
We can use Global key as:
class _ContactUsScreenState extends State<ContactUsScreen> {
//Declare Global Key
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
//key
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text('Contact Us'),
),
body:
}
//use
Future<void> send() async {
final Email email = Email(
body: _bodyController.text,
subject: _subjectController.text,
recipients: [_recipientController.text],
attachmentPaths: attachments,
isHTML: isHTML,
);
String platformResponse;
try {
await FlutterEmailSender.send(email);
platformResponse = 'success';
} catch (error) {
platformResponse = error.toString();
}
if (!mounted) return;
_scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text(platformResponse),
));
}
}
This work using a key in your method build widget.
First create the key:
final GlobalKey<NavigatorState> key =
new GlobalKey<NavigatorState>();
After we bind with our widget:
#override
Widget build(BuildContext context) {
return Scaffold(key:key);
}
Finally we use the key calling .currentContext parameter.
#override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
// your method where use the context
// Example navigate:
Navigator.push(key.currentContext,"SiestaPage");
});
}
Happy coding.