[Catalyst] Fix MainSwitchBarPreference NPE when configuration changed
When activity is recreated (due to configuration is changed), preference screen is created before SettingsActivity sets view layout and results in NPE. As a workaround, save the states inside MainSwitchBarPreference to fix the problem. Bug: 332201912 Flag: EXEMPT library Test: manual Change-Id: I052cd0a521dac203a5f58963c550911e7a741e6f
This commit is contained in:
@@ -17,6 +17,8 @@
|
||||
package com.android.settings.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener
|
||||
import androidx.preference.TwoStatePreference
|
||||
@@ -28,24 +30,30 @@ import com.android.settingslib.widget.MainSwitchBar
|
||||
class MainSwitchBarPreference(context: Context, private val metadata: MainSwitchBarMetadata) :
|
||||
TwoStatePreference(context), OnCheckedChangeListener, MainSwitchBar.PreChangeListener {
|
||||
|
||||
private val mainSwitchBar: MainSwitchBar = (context as SettingsActivity).switchBar
|
||||
// main switch bar might be null when configuration is just changed
|
||||
private val mainSwitchBar: MainSwitchBar?
|
||||
get() = (context as SettingsActivity).switchBar
|
||||
|
||||
override fun setTitle(title: CharSequence?) {
|
||||
mainSwitchBar.setTitle(title)
|
||||
mainSwitchBar?.setTitle(title)
|
||||
super.setTitle(title)
|
||||
}
|
||||
|
||||
override fun setSummary(summary: CharSequence?) {
|
||||
mainSwitchBar.setSummary(summary)
|
||||
mainSwitchBar?.setSummary(summary)
|
||||
super.setSummary(summary)
|
||||
}
|
||||
|
||||
override fun setEnabled(enabled: Boolean) {
|
||||
mainSwitchBar.isEnabled = enabled
|
||||
mainSwitchBar?.isEnabled = enabled
|
||||
super.setEnabled(enabled)
|
||||
}
|
||||
|
||||
// Preference.setVisible is final, we cannot override it
|
||||
fun updateVisibility() {
|
||||
// always make preference invisible, the UI visibility is reflected on MainSwitchBar
|
||||
isVisible = false
|
||||
val mainSwitchBar = mainSwitchBar ?: return
|
||||
if ((metadata as? PreferenceAvailabilityProvider)?.isAvailable(context) != false) {
|
||||
mainSwitchBar.show()
|
||||
} else {
|
||||
@@ -54,6 +62,7 @@ class MainSwitchBarPreference(context: Context, private val metadata: MainSwitch
|
||||
}
|
||||
|
||||
override fun setChecked(checked: Boolean) {
|
||||
val mainSwitchBar = mainSwitchBar ?: return
|
||||
// remove listener to update UI only
|
||||
mainSwitchBar.removeOnSwitchChangeListener(this)
|
||||
mainSwitchBar.isChecked = checked
|
||||
@@ -62,6 +71,7 @@ class MainSwitchBarPreference(context: Context, private val metadata: MainSwitch
|
||||
|
||||
override fun onAttached() {
|
||||
super.onAttached()
|
||||
val mainSwitchBar = mainSwitchBar!!
|
||||
mainSwitchBar.setPreChangeListener(this)
|
||||
mainSwitchBar.addOnSwitchChangeListener(this)
|
||||
}
|
||||
@@ -76,8 +86,65 @@ class MainSwitchBarPreference(context: Context, private val metadata: MainSwitch
|
||||
}
|
||||
|
||||
override fun onDetached() {
|
||||
val mainSwitchBar = mainSwitchBar!!
|
||||
mainSwitchBar.removeOnSwitchChangeListener(this)
|
||||
mainSwitchBar.setPreChangeListener(null)
|
||||
super.onDetached()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(): Parcelable =
|
||||
SavedState(super.onSaveInstanceState()!!).also {
|
||||
it.isEnabled = isEnabled
|
||||
it.title = title
|
||||
it.summary = summary
|
||||
it.mainSwitchBarState = mainSwitchBar?.onSaveInstanceState()
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(state: Parcelable?) {
|
||||
val savedState = state as SavedState
|
||||
super.onRestoreInstanceState(savedState.superState)
|
||||
isEnabled = savedState.isEnabled
|
||||
title = savedState.title
|
||||
summary = savedState.summary
|
||||
mainSwitchBar?.onRestoreInstanceState(savedState.mainSwitchBarState!!)
|
||||
}
|
||||
|
||||
private class SavedState : BaseSavedState {
|
||||
var isEnabled: Boolean = false
|
||||
var title: CharSequence? = null
|
||||
var summary: CharSequence? = null
|
||||
var mainSwitchBarState: Parcelable? = null
|
||||
|
||||
constructor(source: Parcel) : super(source) {
|
||||
isEnabled = source.readBoolean()
|
||||
title = source.readCharSequence()
|
||||
summary = source.readCharSequence()
|
||||
val stateClass = MainSwitchBar.SavedState::class.java
|
||||
mainSwitchBarState = source.readParcelable(stateClass.classLoader, stateClass)
|
||||
}
|
||||
|
||||
constructor(superState: Parcelable) : super(superState)
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
super.writeToParcel(dest, flags)
|
||||
dest.writeBoolean(isEnabled)
|
||||
dest.writeCharSequence(title)
|
||||
dest.writeCharSequence(summary)
|
||||
dest.writeParcelable(mainSwitchBarState, flags)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val CREATOR: Parcelable.Creator<SavedState> =
|
||||
object : Parcelable.Creator<SavedState> {
|
||||
override fun createFromParcel(parcel: Parcel): SavedState {
|
||||
return SavedState(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SavedState?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user