-
Notifications
You must be signed in to change notification settings - Fork 30.2k
PlatformView.onFlutterViewAttached() called multiple times for single instance on Android #178136
Copy link
Copy link
Open
Labels
⏳Bot is counting down the days until it unassigns the issueBot is counting down the days until it unassigns the issueP1High-priority issues at the top of the work listHigh-priority issues at the top of the work lista: platform-viewsEmbedding Android/iOS views in Flutter appsEmbedding Android/iOS views in Flutter appsengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 3.35Found to occur in 3.35Found to occur in 3.35found in release: 3.38Found to occur in 3.38Found to occur in 3.38has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyAndroid applications specificallyteam-androidOwned by Android platform teamOwned by Android platform team
Description
Steps to reproduce
- Run the app with
flutter runon Android - Tap "Show Native View" button
- Check logcat for "DummyNativeView" logs
Expected results
onFlutterViewAttached() should be called once per PlatformView instance.
Actual results
onFlutterViewAttached() is called multiple times for the same PlatformView instance:
Code sample
Code sample
lib/main.dart:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Platform View Test',
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _showNativeView = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Platform View Test'),
),
body: Column(
children: [
ElevatedButton(
onPressed: () {
setState(() {
_showNativeView = !_showNativeView;
});
},
child: Text(_showNativeView ? 'Hide Native View' : 'Show Native View'),
),
Expanded(
child: _showNativeView
? const AndroidView(
viewType: 'dummy_native_view',
layoutDirection: TextDirection.ltr,
)
: const Center(
child: Text('Native view hidden'),
),
),
],
),
);
}
}android/app/src/main/kotlin/com/example/platform_view_test/MainActivity.kt:
package com.example.platform_view_test
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
flutterEngine
.platformViewsController
.registry
.registerViewFactory("dummy_native_view", DummyNativeViewFactory())
}
}android/app/src/main/kotlin/com/example/platform_view_test/DummyNativeViewFactory.kt:
package com.example.platform_view_test
import android.content.Context
import android.util.Log
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
class DummyNativeViewFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
Log.i("DummyNativeView", "Factory.create() called - viewId: $viewId")
return DummyNativeView(context, viewId)
}
}android/app/src/main/kotlin/com/example/platform_view_test/DummyNativeView.kt:
package com.example.platform_view_test
import android.content.Context
import android.graphics.Color
import android.util.Log
import android.view.View
import android.widget.TextView
import io.flutter.plugin.platform.PlatformView
class DummyNativeView(context: Context, private val viewId: Int) : PlatformView {
private val textView: TextView = TextView(context)
init {
Log.i("DummyNativeView", "[$viewId] Constructor called")
textView.apply {
text = "Native Android View #$viewId"
textSize = 20f
setTextColor(Color.WHITE)
setBackgroundColor(Color.BLUE)
setPadding(40, 40, 40, 40)
}
}
override fun getView(): View {
Log.i("DummyNativeView", "[$viewId] getView() called")
return textView
}
override fun dispose() {
Log.i("DummyNativeView", "[$viewId] dispose() called")
}
override fun onFlutterViewAttached(flutterView: View) {
Log.i("DummyNativeView", "[$viewId] onFlutterViewAttached() called")
}
override fun onFlutterViewDetached() {
Log.i("DummyNativeView", "[$viewId] onFlutterViewDetached() called")
}
}Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
DummyNativeView: Factory.create() called - viewId: 0
DummyNativeView: [0] Constructor called
DummyNativeView: [0] getView() called
DummyNativeView: [0] onFlutterViewAttached() called
DummyNativeView: [0] onFlutterViewAttached() called <-- DUPLICATE CALLFlutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.35.7, on macOS 26.0.1 25A362 darwin-arm64, locale en-US) [571ms]
• Flutter version 3.35.7 on channel stable at /Users/romanlaitarenko/Developer/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision adc9010625 (2 weeks ago), 2025-10-21 14:16:03 -0400
• Engine revision 035316565a
• Dart version 3.9.2
• DevTools version 2.48.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-swift-package-manager,
enable-lldb-debugging
[!] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [1,378ms]
• Android SDK at /Users/romanlaitarenko/Library/Android/sdk
• Emulator version 35.5.10.0 (build_id 13402964) (CL:N/A)
• Platform android-36, build-tools 36.0.0
• ANDROID_HOME = /Users/romanlaitarenko/Library/Android/sdk
• Java binary at: /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/bin/java
This JDK is specified in your Flutter configuration.
To change the current JDK, run: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment Temurin-17.0.16+8 (build 17.0.16+8)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 26.1) [992ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 17B55
• CocoaPods version 1.16.2
[✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome) [7ms]
! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
[✓] Android Studio (version 2024.3) [7ms]
• 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 21.0.6+-13368085-b895.109)
[✓] Connected device (3 available) [6.3s]
• sdk gphone16k arm64 (mobile) • emulator-5554 • android-arm64 • Android 15 (API 35) (emulator)
• iPhone 17 Pro (mobile) • 2701564F-9AAF-40CA-8418-AB8BD4C02655 • ios • com.apple.CoreSimulator.SimRuntime.iOS-26-1 (simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 26.0.1 25A362 darwin-arm64
! Error: Browsing on the local area network for Roman’s iPhone (2). Ensure the device is unlocked and attached with a cable or associated with the same local area network as this
Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources [269ms]
• All expected network resources are available.
! Doctor found issues in 2 categories.Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
⏳Bot is counting down the days until it unassigns the issueBot is counting down the days until it unassigns the issueP1High-priority issues at the top of the work listHigh-priority issues at the top of the work lista: platform-viewsEmbedding Android/iOS views in Flutter appsEmbedding Android/iOS views in Flutter appsengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 3.35Found to occur in 3.35Found to occur in 3.35found in release: 3.38Found to occur in 3.38Found to occur in 3.38has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyAndroid applications specificallyteam-androidOwned by Android platform teamOwned by Android platform team