Skip to content

[macOS] UiKitView throws a "PlatformException(recreating_view, trying to create an already created view, view id: '0', null)" after hot-restart #110381

@akaboshinit

Description

@akaboshinit

Steps to Reproduce

  1. Execute flutter run on the code sample
  2. Whenever I develop with UIKitView on macOS and restart, I get [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: PlatformException(recreating_view, trying to create an already created view, view This error occurs. Trying to insert a key or use a unique key for key does not solve the problem.

Expected results:
Ability to restart correctly during development

Actual results:
Duplicate id not reset correctly and error occurs.

I have an idea of the problem, and it's in the error, but it's a duplicate id!
I found an implementation that is issuing ids, but they are either resetting unexpectedly or issuing incorrect ids.

flutter/3.0.5-stable/packages/flutter/lib/src/widgets/platform_view.dart

class PlatformViewsRegistry {
  PlatformViewsRegistry._instance();

  // Always non-negative. The id value -1 is used in the accessibility bridge
  // to indicate the absence of a platform view.
  int _nextPlatformViewId = 0;

  /// Allocates a unique identifier for a platform view.
  ///
  /// A platform view identifier can refer to a platform view that was never created,
  /// a platform view that was disposed, or a platform view that is alive.
  ///
  /// Typically a platform view identifier is passed to a platform view widget
  /// which creates the platform view and manages its lifecycle.
  int getNextPlatformViewId() => _nextPlatformViewId++;
}
Code sample
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  InlineWebViewMacOsController? _controller;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            const UIKitViewErrorMacOsWidget()
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class UIKitViewErrorMacOsWidget extends StatelessWidget {
  const UIKitViewErrorMacOsWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    if (defaultTargetPlatform == TargetPlatform.macOS) {
      return SizedBox(
        width: 200,
        height: 200,
        child: UiKitView(
          key: key,
          viewType: 'uikitview_error_macos_view',
        ),
      );
    }

    return const SizedBox();
  }
}
import Cocoa
import FlutterMacOS

class MainFlutterWindow: NSWindow {
  override func awakeFromNib() {
    let flutterViewController = FlutterViewController.init()
    let windowFrame = self.frame
    self.contentViewController = flutterViewController
    self.setFrame(windowFrame, display: true)

    RegisterGeneratedPlugins(registry: flutterViewController)

    SwiftFlutterPlugin.register(
        with: flutterViewController.registrar(forPlugin: "SwiftFlutterPlugin")
    )

    super.awakeFromNib()
  }
}

public class SwiftFlutterPlugin: NSObject, FlutterPlugin {

    static var instance: SwiftFlutterPlugin?
    var registrar: FlutterPluginRegistrar?

    public init(with registrar: FlutterPluginRegistrar) {
        super.init()

        self.registrar = registrar
        registrar.register(
            NativeViewFactory(messenger: registrar.messenger) as FlutterPlatformViewFactory,
            withId: "uikitview_error_macos_view")
    }

    public static func register(with registrar: FlutterPluginRegistrar) {
        SwiftFlutterPlugin.instance = SwiftFlutterPlugin(with: registrar)
    }

    public func detachFromEngine(for registrar: FlutterPluginRegistrar) {
    }
}

public class NativeViewFactory: NSObject, FlutterPlatformViewFactory
{
    init(messenger: FlutterBinaryMessenger) {
        self.messenger = messenger
        super.init()
    }

    public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
        return FlutterStandardMessageCodec.sharedInstance()
    }
    
    private var messenger: FlutterBinaryMessenger

    public func create(
        withViewIdentifier viewId: Int64,
        arguments args: Any?
    )
        -> NSView
    {
        return NativeView(
            viewIdentifier: viewId,
            arguments: args,
            binaryMessenger: messenger)
    }
}

public func createLabel() -> NSTextField {
    let nativeLabel = NSTextField()
    nativeLabel.frame = CGRect(x: 0, y: 0, width: 180, height: 48.0)
    nativeLabel.stringValue = "Native text from macOS"
    nativeLabel.textColor = NSColor.red
    nativeLabel.isBezeled = false
    nativeLabel.isEditable = false
    nativeLabel.sizeToFit()
    return nativeLabel
}

class NativeView: NSView {

    init(
        viewIdentifier viewId: Int64,
        arguments args: Any?,
        binaryMessenger messenger: FlutterBinaryMessenger?
    ) {
        let frame = CGRect(x: 0, y: 0, width: 200, height: 200)
        super.init(frame: frame)
        super.wantsLayer = true
        super.layer?.backgroundColor = NSColor.blue.cgColor
        super.frame = frame
        super.addSubview(createLabel())
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}
Logs
[   +1 ms] Flutter run key commands.
[        ] r Hot reload. 🔥🔥🔥
[        ] R Hot restart.
[        ] h List all available interactive commands.
[        ] d Detach (terminate "flutter run" but leave application running).
[        ] c Clear the screen
[        ] q Quit (terminate the application on the device).
[        ] 💪 Running with sound null safety 💪
[        ] An Observatory debugger and profiler on macOS is available at: http://127.0.0.1:51030/1RLhAwPR0yE=/
[ +182 ms] The Flutter DevTools debugger and profiler on macOS is available at: http://127.0.0.1:9108?uri=http://127.0.0.1:51030/1RLhAwPR0yE=/
[+11975 ms] Skipping target: gen_localizations
[        ] Skipping target: gen_dart_plugin_registrant
[        ] Skipping target: _composite
[        ] complete
[        ] Performing hot reload...
[   +6 ms] Scanned through 531 files in 3ms
[        ] Syncing files to device macOS...
[        ] Compiling dart to kernel with 0 updated files
[        ] Processing bundle.
[        ] <- recompile package:all/main.dart 2a5f529b-6f22-414a-9aec-669f46f08913
[        ] <- 2a5f529b-6f22-414a-9aec-669f46f08913
[        ] Bundle processing done.
[   +6 ms] Updating files.
[   +1 ms] DevFS: Sync finished
[        ] Syncing files to device macOS... (completed in 8ms)
[        ] Synced 0.0MB.
[   +8 ms] Reassembling application
[  +34 ms] Hot reload performed in 55ms.
[        ] Performing hot reload... (completed in 58ms)
[        ] Reloaded 0 libraries in 62ms.
[+1764 ms] Skipping target: gen_localizations
[        ] Skipping target: gen_dart_plugin_registrant
[        ] Skipping target: _composite
[        ] complete
[        ] Performing hot restart...
[   +3 ms] Scanned through 531 files in 2ms
[        ] Syncing files to device macOS...
[        ] <- reset
[        ] Compiling dart to kernel with 0 updated files
[        ] Processing bundle.
[        ] <- recompile package:all/main.dart dddac9ea-9201-45eb-99ba-7727e5adce2d
[        ] <- dddac9ea-9201-45eb-99ba-7727e5adce2d
[        ] Bundle processing done.
[  +36 ms] Updating files.
[  +14 ms] DevFS: Sync finished
[        ] Syncing files to device macOS... (completed in 52ms)
[        ] Synced 29.3MB.
[        ] <- accept
[ +196 ms] Hot restart performed in 252ms.
[        ] Performing hot restart... (completed in 254ms)
[        ] Restarted application in 256ms.
[ +317 ms] [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: PlatformException(recreating_view, trying to create an already created view, view
id: '0', null)
[        ] #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
[        ] #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:167:18)
[        ] <asynchronous suspension>
[        ] #2      PlatformViewsService.initUiKitView (package:flutter/src/services/platform_views.dart:229:5)
[        ] <asynchronous suspension>
[        ] #3      _UiKitViewState._createNewUiKitView (package:flutter/src/widgets/platform_view.dart:639:44)
[        ] <asynchronous suspension>
% flutter analyze
Analyzing all...                                                        
No issues found! (ran in 1.4s)
% flutter doctor -v
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.0.1 21A559 darwin-arm, locale ja-JP)
    • Flutter version 3.0.5 at /Users/redstar16/.asdf/installs/flutter/3.0.5-stable
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f1875d570e (6 weeks ago), 2022-07-13 11:24:16 -0700
    • Engine revision e85ea0e79c
    • Dart version 2.17.6
    • DevTools version 2.12.2

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at /Users/redstar16/Library/Android/sdk
    • Platform android-31, build-tools 31.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2020.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)

[✓] VS Code (version 1.70.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.46.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 12.0.1 21A559 darwin-arm
    • Chrome (web)    • chrome • web-javascript • Google Chrome 104.0.5112.101

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: platform-viewsEmbedding Android/iOS views in Flutter appsc: crashStack traces logged to the consoleengineflutter/engine related. See also e: labels.found in release: 3.0Found to occur in 3.0found in release: 3.1Found to occur in 3.1has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-macBuilding on or for macOS specificallyr: fixedIssue is closed as already fixed in a newer versionteam-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions