'value.isInitialized': is not true || Flutter desktop error

350 Views Asked by At

I am working on Blockly(Blockly is a client-side library for the programming language JavaScript for creating block-based visual programming languages and editors) for the flutter desktop windows. I am using the webview_windows package to display 'https://developers.google.com/blockly' in a webview.

below is my code

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';

import 'package:webview_windows/webview_windows.dart';

 final navigatorKey = GlobalKey<NavigatorState>();

void main() {
runApp(MyApp());
}  

 class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
   return MaterialApp(navigatorKey: navigatorKey, home: ExampleBrowser());
  }
}

 class ExampleBrowser extends StatefulWidget {
 @override
 State<ExampleBrowser> createState() => _ExampleBrowser();
}

class _ExampleBrowser extends State<ExampleBrowser> {
final _controller = WebviewController();
final _textController = TextEditingController();
 bool _isWebviewSuspended = false;

 @override
 void initState() {
     super.initState();
      initPlatformState();
     }

     Future<void> initPlatformState() async {
       try {
        await _controller.initialize();
        _controller.url.listen((url) {
         _textController.text = URL;
         });

      await _controller.setBackgroundColor(Colors.transparent);
      await _controller.setPopupWindowPolicy(WebviewPopupWindowPolicy.deny);
      await _controller.loadUrl('https://developers.google.com/blockly');

  if (!mounted) return;
  setState(() {});
} on PlatformException catch (e) {
  WidgetsBinding.instance?.addPostFrameCallback((_) {
    showDialog(
        context: context,
        builder: (_) => AlertDialog(
              title: Text('Error'),
              content: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Code: ${e.code}'),
                  Text('Message: ${e.message}'),
                ],
              ),
              actions: [
                TextButton(
                  child: Text('Continue'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                )
              ],
            ));
   });
  }
 }

 Widget compositeView() {
  if (!_controller.value.isInitialized) {
  return const Text(
    'Not Initialized',
    style: TextStyle(
      fontSize: 24.0,
      fontWeight: FontWeight.w900,
    ),
  );
} else {
  return Padding(
    padding: EdgeInsets.all(20),
    child: Column(
      children: [
        Card(
          elevation: 0,
          child: TextField(
            decoration: InputDecoration(
                hintText: 'URL',
                contentPadding: EdgeInsets.all(10.0),
                suffixIcon: IconButton(
                  icon: Icon(Icons.refresh),
                  onPressed: () {
                    _controller.reload();
                  },
                )),
            textAlignVertical: TextAlignVertical.center,
            controller: _textController,
            onSubmitted: (val) {
              _controller.loadUrl(val);
            },
          ),
        ),
        Expanded(
            child: Card(
                color: Colors.transparent,
                elevation: 0,
                clipBehavior: Clip.antiAliasWithSaveLayer,
                child: Stack(
                  children: [
                    Webview(
                      _controller,
                      permissionRequested: _onPermissionRequested,
                    ),
                    StreamBuilder<LoadingState>(
                        stream: _controller.loadingState,
                        builder: (context, snapshot) {
                          if (snapshot.hasData &&
                              snapshot.data == LoadingState.loading) {
                            return LinearProgressIndicator();
                          } else {
                            return SizedBox();
                          }
                        }),
                  ],
                ))),
      ],
    ),
    );
  }
  }

  @override
    Widget build(BuildContext context) {
    return Scaffold(
    floatingActionButton: FloatingActionButton(
    tooltip: _isWebviewSuspended ? 'Resume webview' : 'Suspend webview',
    onPressed: () async {
      if (_isWebviewSuspended) {
        await _controller.resume();
      } else {
        await _controller.suspend();
      }
      setState(() {
        _isWebviewSuspended = !_isWebviewSuspended;
      });
    },
    child: Icon(_isWebviewSuspended ? Icons.play_arrow : Icons.pause),
  ),
  appBar: AppBar(
      title: StreamBuilder<String>(
    stream: _controller.title,
    builder: (context, snapshot) {
      return Text(
          snapshot.hasData ? snapshot.data! : 'WebView (Windows) Example');
    },
  )),
    body: Center(
      child: compositeView(),
      ),
     );
  }

Future<WebviewPermissionDecision> _onPermissionRequested(
    String url, WebviewPermissionKind kind, bool isUserInitiated) async {
    final decision = await showDialog<WebviewPermissionDecision>(
    context: navigatorKey.currentContext!,
    builder: (BuildContext context) => AlertDialog(
    title: const Text('WebView permission requested'),
    content: Text('WebView has requested permission \'$kind\''),
    actions: <Widget>[
      TextButton(
        onPressed: () =>
            Navigator.pop(context, WebviewPermissionDecision.deny),
        child: const Text('Deny'),
      ),
      TextButton(
        onPressed: () =>
            Navigator.pop(context, WebviewPermissionDecision.allow),
        child: const Text('Allow'),
      ),
    ],
  ),
  );

    return decision ?? WebviewPermissionDecision.none;
  }
}

and here is my error in console error

1

There are 1 best solutions below

1
On

I had the same issue in a diffetent scenario, what I did was to do a Future.delayed of 1 second to the other functions inside the controller, in my case the exception is thrown inside setBackgroundColor (which was called right after initialize()) saying value.isInitialized is not true after controller is initialized, here an example:

    Future.wait([
      _windowsWebViewController.initialize(),
      _windowsWebViewController.setBackgroundColor(Colors.transparent),
      _windowsWebViewController.setPopupWindowPolicy(WebviewPopupWindowPolicy.allow),
      _windowsWebViewController.loadUrl(element.url.toString().indexOf('.pdf') != -1
          ? 'https://docs.google.com/gview?embedded=true&url=${element.url.toString()}'
          : element.url.toString()),
    ]);

Here the solution:

Future.wait([
      _windowsWebViewController.initialize(),
    ]);

    Future.delayed(Duration(seconds: 1), () {

      _windowsWebViewController.setBackgroundColor(Colors.transparent);
      _windowsWebViewController.setPopupWindowPolicy(WebviewPopupWindowPolicy.allow);
      _windowsWebViewController.loadUrl(element.url.toString().indexOf('.pdf') != -1
      ? 'https://docs.google.com/gview?embedded=true&url=${element.url.toString()}'
          : element.url.toString());

    });

For some reason even though we initialize the controller, the rest of the methods inside of it do not get notify about the value inside the controller when it changes, even though we use await to complete the initialization.