Android SDK开发:能否将Flutter Widget嵌入Android View?
Absolutely feasible! You can embed a full-featured Flutter widget (with complete routing and UI) into your View-only Android SDK without relying on Activity or Fragment. Here's a step-by-step breakdown to make it work:
1. 配置Flutter AAR依赖
First, add your Flutter AAR to your project. Place the generated flutter_release.aar (and related embedding AARs if needed) in your module's libs directory, then update your module's build.gradle to include the dependency:
dependencies { implementation files('libs/flutter_release.aar') // Include other required Flutter embedding dependencies if necessary implementation files('libs/flutter_embedding_release.aar') implementation files('libs/flutter_services_release.aar') }
2. 管理FlutterEngine生命周期
Since you're using View.OnAttachStateChangeListener to track your host View's lifecycle, you can initialize and destroy the FlutterEngine (the core of Flutter's Android embedding) in these callbacks. This ensures proper resource management and avoids memory leaks.
Here's a sample custom host View implementation:
class FlutterHostContainer @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr), View.OnAttachStateChangeListener { private var flutterEngine: FlutterEngine? = null private var flutterView: FlutterView? = null init { // Register the attach/detach listener addOnAttachStateChangeListener(this) } override fun onViewAttachedToWindow(view: View) { // Initialize FlutterEngine with Application Context to avoid Activity dependencies flutterEngine = FlutterEngine(context.applicationContext).apply { // Execute your Flutter app's entrypoint (matches your Dart main() function) dartExecutor.executeDartEntrypoint( DartExecutor.DartEntrypoint.createDefault() ) } // Create FlutterView and attach it to the engine flutterView = FlutterView(context).apply { // Set layout params to fill the host container layoutParams = LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) attachToFlutterEngine(flutterEngine!!) } // Add FlutterView to your host layout addView(flutterView) } override fun onViewDetachedFromWindow(view: View) { // Clean up resources to prevent memory leaks flutterView?.detachFromFlutterEngine() flutterEngine?.destroy() flutterView = null flutterEngine = null } }
3. 使用你的Flutter Widget
The Dart code you provided works perfectly here! The MaterialApp already includes a full routing system, so you can navigate between screens just like a regular Flutter app. For example, if you add a button that navigates to a new screen:
// Inside _MyHomePageState's build method, add a button to the Column ElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => SecondScreen()), ); }, child: Text('Go to Second Screen'), )
This routing will function normally within the embedded FlutterView.
Key Notes & Best Practices
- Memory Management: Each
FlutterEngineconsumes significant memory. If your SDK creates multiple instances of the host View, consider reusing a single globalFlutterEngine(ensure thread safety and proper lifecycle handling). - Permissions: If your Flutter widget needs access to features like network, storage, or location, make sure the host app adds the corresponding permissions to its
AndroidManifest.xml. - Obfuscation: Add these rules to your
proguard-rules.proto avoid breaking Flutter's embedded logic:-keep class io.flutter.app.** { *; } -keep class io.flutter.plugin.** { *; } -keep class io.flutter.util.** { *; } -keep class io.flutter.view.** { *; } -keep class io.flutter.** { *; } -keep class io.flutter.plugins.** { *; } - Version Compatibility: Ensure your Flutter AAR version matches the compile SDK and target SDK versions of your Android project to avoid compatibility issues.
内容的提问来源于stack exchange,提问作者BennyP

