This feature I'm trying out in Flutter is called Add-to-App.
I read the instructions included in their documentation on how I can add FlutterFragment
as a section in my app.
As seen in the document example, I should be able to add my newFlutterFragment
just like how I add normal Fragment
classes in Android.
// Create and attach a FlutterFragment if one does not exist.
if (flutterFragment == null) {
var newFlutterFragment = FlutterFragment.createDefault()
flutterFragment = newFlutterFragment
fragmentManager
.beginTransaction()
.add(
R.id.fragment_container,
newFlutterFragment,
TAG_FLUTTER_FRAGMENT
)
.commit()
}
The examples we're pretty much straightforward, however, as per checking (Github and SO), it only works when you are warming up a FlutterEngine
using the main
or default entry point.
Unfortunately, whenever I try adding my own FlutterFragment
using a custom entry point, it doesn't seem to accept the type of object I'm passing in the .add(<INVALID_TYPE>,...,...)
method of the FragmentTransaction
.
Is there by any chance that I could still use FlutterFragment
as the container for the Flutter section view I have?
Setup
Environment
What went wrong?
As of the moment, if you are using AndroidX, the only way you can use FlutterFragment
in embedding your Flutter layout is when it is added as an Android Archive (AAR) in your dependencies.
I've previously opened an issue in Github regarding this concern, and it is still open at the time of writing.
Adding Flutter as an AAR dependency has both pros and cons. With AAR, your team does not need to have Flutter SDK installed in their local machine nor required to install Dart SDK. However, since AAR files are compiled artifacts, your team may not be able to edit the project's Flutter source code during development.
Here's the documentation on how you can setup your Android project with your Flutter source code added as an AAR module.
But why really use AAR?
Under the hood, FlutterFragment
and some (if not all) of the classes under
io.flutter.embedding
are still using the support libraries and not AndroidX, there is a mismatch in the dependencies. With AAR and with your jetifier enabled during compilation, the AAR output of your Flutter will now use equivalent AndroidX libraries, something you don't expect to happen during runtime .
But, I need my team to work on some Flutter app features simultaneously with some Android app project changes.
Well, since you can't use FlutterFragment
in that particular type of setup, you can still use FlutterView
, especially if you are only showing a portion of your Flutter layout in your Android app.
feature_fragment.kt
portfolioEngine?.let { flutterEngine ->
// Start executing Dart code to pre-warm the FlutterEngine.
// https://github.com/flutter/flutter/wiki/Experimental:-Launch-Flutter-with-non-main-entrypoint
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint(
FlutterMain.findAppBundlePath(),
"customEntryPoint"
)
)
// Cache the FlutterEngine to be used by FlutterActivity.
FlutterEngineCache
.getInstance()
.put("SOME_FLUTTER_ENGINE_NAME", flutterEngine)
// Add the Flutter layout
flutterView = FlutterView(context)
flutterView.attachToFlutterEngine(flutterEngine)
flutterContainerView?.removeAllViews() // Only if deemed necessary
flutterContainerView?.addView(flutterView)
}
feature_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/flutterContainerView"
android:layout_width="match_parent"
android:layout_height="300dp" />
</LinearLayout>
But, there's a small catch...
One of the benefits using FlutterActivity
or FlutterFragment
over FlutterView
is the ease of managing the lifecycle of your Android and Flutter code simultaneously. Don't worry, you can still handle how your Flutter code will behave by managing its lifecycle using the attached FlutterEngine
.
Further reading