Запрошенный движок флаттера не существует в Добавить в приложение

У меня есть флаттер в существующем родном приложении (Добавить в приложение) с кэшированным движком флаттера.

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 ответа

Решение

Как воспроизвести

  1. Откройте настройки разработчика, установите "Фоновые процессы" на "Без фоновых процессов" и установите "Не сохранять действия".

  2. Откройте приложение, нажмите и домой

  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)

Это обходной путь, не ясное решение, я думаю, мы все еще ждем исправления из ядра

Другие вопросы по тегам