Android. Как запретить пересоздавать Activity при смене ночной/дневной темы?
На устройстве можно через шторку менять тему на ночную/дневную. И при смене темы мое приложение закрывается с ошибкой, связанной с пересозданием Activity и DialogFragment.
Лог прилагаю:
2022-03-01 02:00:46.586 16041-16041/com.p.test.app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.p.test.app, PID: 16041
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.p.test.app/com.p.test.app.ui.MainActivity}: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.p.test.app.ui.dialogs.ActivityDialogFragment: could not find Fragment constructor
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4060)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4247)
at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:6253)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:6144)
at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2613)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8668)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)
Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.p.test.app.ui.dialogs.ActivityDialogFragment: could not find Fragment constructor
at androidx.fragment.app.Fragment.instantiate(Fragment.java:628)
at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:483)
at androidx.fragment.app.FragmentStateManager.<init>(FragmentStateManager.java:85)
at androidx.fragment.app.FragmentManager.restoreSaveState(FragmentManager.java:2728)
at androidx.fragment.app.FragmentController.restoreSaveState(FragmentController.java:198)
at androidx.fragment.app.FragmentActivity$2.onContextAvailable(FragmentActivity.java:149)
at androidx.activity.contextaware.ContextAwareHelper.dispatchOnContextAvailable(ContextAwareHelper.java:99)
at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:322)
at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:273)
at com.p.test.app.ui.MainActivity.onCreate(MainActivity.kt:50)
at android.app.Activity.performCreate(Activity.java:8214)
at android.app.Activity.performCreate(Activity.java:8202)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1320)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4033)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4247)
at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:6253)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:6144)
at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2613)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8668)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)
Caused by: java.lang.NoSuchMethodException: com.p.test.app.ui.dialogs.ActivityDialogFragment.<init> []
at java.lang.Class.getConstructor0(Class.java:2332)
at java.lang.Class.getConstructor(Class.java:1728)
at androidx.fragment.app.Fragment.instantiate(Fragment.java:613)
at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:483)
at androidx.fragment.app.FragmentStateManager.<init>(FragmentStateManager.java:85)
at androidx.fragment.app.FragmentManager.restoreSaveState(FragmentManager.java:2728)
at androidx.fragment.app.FragmentController.restoreSaveState(FragmentController.java:198)
at androidx.fragment.app.FragmentActivity$2.onContextAvailable(FragmentActivity.java:149)
Мне нужно как то запретить это "пересоздание", или не использовать фрагменты?
Upd: эта ошибка возникает если в момент переключения темы был открыт диалог DialogFragment
Код класса ActivityDialogFragment:
open class ActivityDialogFragment(val activity: Activity) : DialogFragment() {
var rootView: FrameLayout? = null
var dialogContentView: ViewGroup? = null
init {
rootView = FrameLayout(activity)
val view: View = LayoutInflater.from(activity).inflate(R.layout.app_dialog, null)
dialogContentView = view.findViewById(R.id.dialogContent)
rootView!!.addView(view)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder: AlertDialog.Builder = AlertDialog.Builder(requireActivity(), R.style.FullScreen)
val dialog = builder.create()
dialog.window!!.attributes.windowAnimations = R.style.ActivityDialogFragment_Default_Animation
return dialog
}
override fun onStart() {
super.onStart()
val window = dialog!!.window!!
window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
window.setDimAmount(0.00f)
window.setLayout(
activity.window.decorView.width,
activity.window.decorView.height)
rootView!!.layoutParams = ViewGroup.LayoutParams(
activity.window.decorView.width,
activity.window.decorView.height)
dialog!!.setContentView(rootView!!)
rootView!!.setOnClickListener {
dismiss()
}
}
open fun setContent(content: View){
dialogContentView?.addView(content)
}
}
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.p.test.app">
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.App">
<activity
android:name=".ui.WelcomeActivity"
android:exported="true"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="adjustPan" />
</application>
</manifest>
Ответы (1 шт):
Автор решения: imworse
→ Ссылка
Чтобы приложение игнорировало изменение ночной/дневной темы, нужно добавить в манифест активити android:configChanges="uiMode"