Reputation: 4165
I have flutter into the existing native app (Add to app) with a cached flutter engine.
override fun onCreate(savedInstanceState: Bundle?) {
Log.d(TAG, "onCreate")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
context = this.application.applicationContext
if (!FlutterEngineCache.getInstance().contains(
FLUTTER_ENGINE
)
) {
mFlutterEngine = FlutterEngine(context)
mFlutterEngine.dartExecutor
.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())
FlutterEngineCache.getInstance()
.put(FLUTTER_ENGINE, mFlutterEngine)
}
//Create Flutter Fragment
mFragmentManager = supportFragmentManager
mFlutterFragment = mFragmentManager.findFragmentByTag(FLUTTER_FRAGMENT) as FlutterFragment?
if (mFlutterFragment == null) {
mFlutterFragment =
FlutterFragment.withCachedEngine(FLUTTER_ENGINE).transparencyMode(FlutterView.TransparencyMode.opaque).build()
mFragmentManager
.beginTransaction()
.add(R.id.fragment_container, mFlutterFragment as Fragment, FLUTTER_FRAGMENT)
.commit()
} else {
mFragmentManager
.beginTransaction()
.show(mFragmentManager.findFragmentByTag(FLUTTER_FRAGMENT)!!)
.commit()
}
}
I am getting the following crash in the production app
Caused by: java.lang.IllegalStateException: The requested cached FlutterEngine did not exist in the FlutterEngineCache: 'FLUTTER_ENGINE'
at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.setupFlutterEngine(FlutterActivityAndFragmentDelegate.java:211)
at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onAttach(FlutterActivityAndFragmentDelegate.java:157)
at io.flutter.embedding.android.FlutterFragment.onAttach(FlutterFragment.java:597)
at androidx.fragment.app.Fragment.performAttach(Fragment.java:2574)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:828)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2659)
at androidx.fragment.app.FragmentManagerImpl.dispatchCreate(FragmentManagerImpl.java:2607)
at androidx.fragment.app.FragmentController.dispatchCreate(FragmentController.java:235)
at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:316)
at androidx.appcompat.app.AppCompatActivity.onCreate(AppCompatActivity.java:106)
at com.flutter.android.MainActivity.onCreate(MainActivity.kt:33)
Upvotes: 8
Views: 3954
Reputation: 1134
I think the problem here is that when OS auto kills activity, then all cache engines be killed, and when you re-open your app, you must control which engineId your flutter activity needs.
Example:
engineId0
) => details (cache engineId1
), and you put your engine name in ascending order (engineId1, engineId2, engineId3...). When you're on details page, you put your app into the background and use other apps, then sometimes OS auto kill your activity.engineId0
(the first in your stack engines), then your code using this engine, but seem savedInstanceState at super.onCreate still remembers and requests engineId1
at this details page => that cause the issue.Solution:
super.onCreate(null)
then it won't request engineId1
like my example above.Upvotes: 1
Reputation: 4165
How to reproduce
Open developer settings, set "Background processes" to "No Background Processes" and set on the Don't keep activities.
Open the app press and home
Open the app again .. it will crash with the exception.
Caused by: java.lang.IllegalStateException: The requested cached FlutterEngine did not exist in the FlutterEngineCache: 'FLUTTER_ENGINE'
Solution
initialize the flutter engine before super.oncreate()
override fun onCreate(savedInstanceState: Bundle?) {
Log.d(TAG, "onCreate")
context = this.application.applicationContext
if (!FlutterEngineCache.getInstance().contains(
FLUTTER_ENGINE
)
) {
mFlutterEngine = FlutterEngine(context)
mFlutterEngine.dartExecutor
.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())
FlutterEngineCache.getInstance()
.put(FLUTTER_ENGINE, mFlutterEngine)
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Create Flutter Fragment
mFragmentManager = supportFragmentManager
mFlutterFragment = mFragmentManager.findFragmentByTag(FLUTTER_FRAGMENT) as FlutterFragment?
if (mFlutterFragment == null) {
mFlutterFragment =
FlutterFragment.withCachedEngine(FLUTTER_ENGINE).transparencyMode(FlutterView.TransparencyMode.opaque).build()
mFragmentManager
.beginTransaction()
.add(R.id.fragment_container, mFlutterFragment as Fragment, FLUTTER_FRAGMENT)
.commit()
} else {
mFragmentManager
.beginTransaction()
.show(mFragmentManager.findFragmentByTag(FLUTTER_FRAGMENT)!!)
.commit()
}
Upvotes: 5