[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
|
package com.android.settings.widget
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Parcel
|
||||||
|
import android.os.Parcelable
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener
|
import android.widget.CompoundButton.OnCheckedChangeListener
|
||||||
import androidx.preference.TwoStatePreference
|
import androidx.preference.TwoStatePreference
|
||||||
@@ -28,24 +30,30 @@ import com.android.settingslib.widget.MainSwitchBar
|
|||||||
class MainSwitchBarPreference(context: Context, private val metadata: MainSwitchBarMetadata) :
|
class MainSwitchBarPreference(context: Context, private val metadata: MainSwitchBarMetadata) :
|
||||||
TwoStatePreference(context), OnCheckedChangeListener, MainSwitchBar.PreChangeListener {
|
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?) {
|
override fun setTitle(title: CharSequence?) {
|
||||||
mainSwitchBar.setTitle(title)
|
mainSwitchBar?.setTitle(title)
|
||||||
|
super.setTitle(title)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setSummary(summary: CharSequence?) {
|
override fun setSummary(summary: CharSequence?) {
|
||||||
mainSwitchBar.setSummary(summary)
|
mainSwitchBar?.setSummary(summary)
|
||||||
|
super.setSummary(summary)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setEnabled(enabled: Boolean) {
|
override fun setEnabled(enabled: Boolean) {
|
||||||
mainSwitchBar.isEnabled = enabled
|
mainSwitchBar?.isEnabled = enabled
|
||||||
|
super.setEnabled(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preference.setVisible is final, we cannot override it
|
// Preference.setVisible is final, we cannot override it
|
||||||
fun updateVisibility() {
|
fun updateVisibility() {
|
||||||
// always make preference invisible, the UI visibility is reflected on MainSwitchBar
|
// always make preference invisible, the UI visibility is reflected on MainSwitchBar
|
||||||
isVisible = false
|
isVisible = false
|
||||||
|
val mainSwitchBar = mainSwitchBar ?: return
|
||||||
if ((metadata as? PreferenceAvailabilityProvider)?.isAvailable(context) != false) {
|
if ((metadata as? PreferenceAvailabilityProvider)?.isAvailable(context) != false) {
|
||||||
mainSwitchBar.show()
|
mainSwitchBar.show()
|
||||||
} else {
|
} else {
|
||||||
@@ -54,6 +62,7 @@ class MainSwitchBarPreference(context: Context, private val metadata: MainSwitch
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setChecked(checked: Boolean) {
|
override fun setChecked(checked: Boolean) {
|
||||||
|
val mainSwitchBar = mainSwitchBar ?: return
|
||||||
// remove listener to update UI only
|
// remove listener to update UI only
|
||||||
mainSwitchBar.removeOnSwitchChangeListener(this)
|
mainSwitchBar.removeOnSwitchChangeListener(this)
|
||||||
mainSwitchBar.isChecked = checked
|
mainSwitchBar.isChecked = checked
|
||||||
@@ -62,6 +71,7 @@ class MainSwitchBarPreference(context: Context, private val metadata: MainSwitch
|
|||||||
|
|
||||||
override fun onAttached() {
|
override fun onAttached() {
|
||||||
super.onAttached()
|
super.onAttached()
|
||||||
|
val mainSwitchBar = mainSwitchBar!!
|
||||||
mainSwitchBar.setPreChangeListener(this)
|
mainSwitchBar.setPreChangeListener(this)
|
||||||
mainSwitchBar.addOnSwitchChangeListener(this)
|
mainSwitchBar.addOnSwitchChangeListener(this)
|
||||||
}
|
}
|
||||||
@@ -76,8 +86,65 @@ class MainSwitchBarPreference(context: Context, private val metadata: MainSwitch
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDetached() {
|
override fun onDetached() {
|
||||||
|
val mainSwitchBar = mainSwitchBar!!
|
||||||
mainSwitchBar.removeOnSwitchChangeListener(this)
|
mainSwitchBar.removeOnSwitchChangeListener(this)
|
||||||
mainSwitchBar.setPreChangeListener(null)
|
mainSwitchBar.setPreChangeListener(null)
|
||||||
super.onDetached()
|
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