Запрошенный движок флаттера не существует в Добавить в приложение
У меня есть флаттер в существующем родном приложении (Добавить в приложение) с кэшированным движком флаттера.
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()
}
}
Я получаю следующий сбой в производственном приложении
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)
3 ответа
Как воспроизвести
Откройте настройки разработчика, установите "Фоновые процессы" на "Без фоновых процессов" и установите "Не сохранять действия".
Откройте приложение, нажмите и домой
Снова откройте приложение.. оно вылетит за исключением.
Вызвано: java.lang.IllegalStateException: запрошенный кэшированный FlutterEngine не существует во FlutterEngineCache: 'FLUTTER_ENGINE'
Решение
инициализировать двигатель флаттера перед
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()
}
Я думаю, что проблема здесь в том, что когда ОС автоматически убивает активность, тогда все механизмы кеширования будут убиты, и когда вы повторно открываете свое приложение, вы должны контролировать, какой engineId нужен вашей активности флаттера.
Пример:
- В вашем приложении есть 2 действия: главная (кеш) => детали (кеш), и вы указываете имя своего движка в порядке возрастания (engineId1, engineId2, engineId3...). Когда вы находитесь на странице сведений, вы помещаете свое приложение в фоновый режим и используете другие приложения, а иногда ОС автоматически убивает вашу активность.
- Когда вы вернетесь в свое приложение, оно откроет страницу сведений (и, конечно же, снова перейдете на Create), но проблема здесь в том, что все движки будут убиты, затем вы проверяете, что движок не существует, и воссоздаете
(первый в ваших стековых движках), затем ваш код, использующий этот движок, но похоже, что savedInstanceState в super.onCreate все еще запоминает и запрашивает на этой странице сведений =>, которые вызывают проблему.
Решение:
- Вы должны найти способ назвать свой движок, а не в порядке возрастания.
- Передача null в super.onCreate как это
тогда он не будет запрашивать как в моем примере выше.
Кажется, эта ошибка является основной ошибкой (проверка на примере репозитория flutter, проблема все еще возникает), решение с инициализацией механизма flutter перед super.onCreate() не работает в моем случае.
Пример:
- У меня есть flutterActivity1 с cacheEngine1 и flutterActivity2 с cacheEngine2 , затем запускаю их оба, когда я нажимаю home btn и запускаю другое приложение (для воспроизведения активности автоматического уничтожения ОС).
- После этого оба flutterActivity1 и flutterActivity2 будут убиты, и, похоже, весь механизм кеширования тоже исчез. Затем я возвращаюсь в свое приложение, оно открывает flutterActivity1 (а кеша нет, поэтому я снова инициализирую cacheEngine1 ).
- Проблема в том, что ядро флаттера все еще проверяет cacheEngine2, а затем генерирует это исключение
- Я думаю, что механизм кеширования убит системой ОС (не обычным способом убить флаттером или программно), поэтому флаттер все еще думает, что этот движок существует, и проверяет его после этого
Итак, мое решение передает null в super.onCreate
super.onCreate(null)
Это обходной путь, не ясное решение, я думаю, мы все еще ждем исправления из ядра