如何将 LiveData 保存到 saveStateHandle 中?
How to save LiveData into saveStateHandle?
如所示,我们可以将LiveData保存在savedStateHandle中。
我可以轻松做到
private val textLiveData: MutableLiveData<String>
init {
textLiveData = savedStateHandle.getLiveData(KEY)
}
但是,当尝试如下保存时,
savedStateHandle.set(KEY, textLiveData)
我收到错误
java.lang.IllegalArgumentException: Can't put value with type class androidx.lifecycle.SavedStateHandle$SavingStateLiveData into saved state
我哪里弄错了?
查看代码后,意识到我只需要保存值,就像@Parth 在上面的评论中提到的那样。
savedStateHandle.set(KEY, textLiveData.value)
说明
如果我们查看 SavedStateHandle.java
的 set
@MainThread
public <T> void set(@NonNull String key, @Nullable T value) {
validateValue(value);
@SuppressWarnings("unchecked")
MutableLiveData<T> mutableLiveData = (MutableLiveData<T>) mLiveDatas.get(key);
if (mutableLiveData != null) {
// it will set value;
mutableLiveData.setValue(value);
} else {
mRegular.put(key, value);
}
}
这说明如果有的话,它会把数据放到我们存入mLiveDatas
的mutableLiveData
中。
为了确保我们的liveData在mLiveDatas
,我们只需要在开始时使用textLiveData = savedStateHandle.getLiveData(KEY)
。检查 getLiveData
的
SavedStateHandle.java
@NonNull
private <T> MutableLiveData<T> getLiveDataInternal(
@NonNull String key,
boolean hasInitialValue,
@Nullable T initialValue) {
MutableLiveData<T> liveData = (MutableLiveData<T>) mLiveDatas.get(key);
if (liveData != null) {
return liveData;
}
SavingStateLiveData<T> mutableLd;
// double hashing but null is valid value
if (mRegular.containsKey(key)) {
mutableLd = new SavingStateLiveData<>(this, key, (T) mRegular.get(key));
} else if (hasInitialValue) {
mutableLd = new SavingStateLiveData<>(this, key, initialValue);
} else {
mutableLd = new SavingStateLiveData<>(this, key);
}
mLiveDatas.put(key, mutableLd);
return mutableLd;
}
当我们请求一个时,它会创建一个并放入 mLiveDatas
,如果还没有。
显然更好的答案是,我们甚至不需要
savedStateHandle.set(KEY, textLiveData.value)
虽然这是允许的,但当我们设置
textLiveData.value = "Some data"
这已经保存到状态。由于 textLiveData
是从 savedStateHandle
中检索到的,如下所示。
textLiveData = savedStateHandle.getLiveData(KEY)
因此 textLiveData
已经存储在 savedStateHandle
中,对 textLiveData.value
的更改无意中保存在 savedStateHandle
中。
您可以使用 val textLiveData: MutableLiveData<String> = savedStateHandle.getLiveData(KEY)
构造一个 MutableLiveData
并自动保存到 savedInstanceState
。
savedStateHandle.set(KEY, textLiveData)
你不需要这样做,因为 getLiveData
是一个 SavingStateLiveData
,它会自动处理这个。
那是因为你的你class不接受。
您可以输入 Parcelable
或 Serializable
类型。
这是ACCEPTABLE_CLASSES
的列表
private static final Class[] ACCEPTABLE_CLASSES = new Class[]{
//baseBundle
boolean.class,
boolean[].class,
double.class,
double[].class,
int.class,
int[].class,
long.class,
long[].class,
String.class,
String[].class,
//bundle
Binder.class,
Bundle.class,
byte.class,
byte[].class,
char.class,
char[].class,
CharSequence.class,
CharSequence[].class,
// type erasure ¯\_(ツ)_/¯, we won't eagerly check elements contents
ArrayList.class,
float.class,
float[].class,
Parcelable.class,
Parcelable[].class,
Serializable.class,
short.class,
short[].class,
SparseArray.class,
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? Size.class : int.class),
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? SizeF.class : int.class),
};
如所示,我们可以将LiveData保存在savedStateHandle中。
我可以轻松做到
private val textLiveData: MutableLiveData<String>
init {
textLiveData = savedStateHandle.getLiveData(KEY)
}
但是,当尝试如下保存时,
savedStateHandle.set(KEY, textLiveData)
我收到错误
java.lang.IllegalArgumentException: Can't put value with type class androidx.lifecycle.SavedStateHandle$SavingStateLiveData into saved state
我哪里弄错了?
查看代码后,意识到我只需要保存值,就像@Parth 在上面的评论中提到的那样。
savedStateHandle.set(KEY, textLiveData.value)
说明
如果我们查看 SavedStateHandle.java
的 set
@MainThread
public <T> void set(@NonNull String key, @Nullable T value) {
validateValue(value);
@SuppressWarnings("unchecked")
MutableLiveData<T> mutableLiveData = (MutableLiveData<T>) mLiveDatas.get(key);
if (mutableLiveData != null) {
// it will set value;
mutableLiveData.setValue(value);
} else {
mRegular.put(key, value);
}
}
这说明如果有的话,它会把数据放到我们存入mLiveDatas
的mutableLiveData
中。
为了确保我们的liveData在mLiveDatas
,我们只需要在开始时使用textLiveData = savedStateHandle.getLiveData(KEY)
。检查 getLiveData
的
SavedStateHandle.java
@NonNull
private <T> MutableLiveData<T> getLiveDataInternal(
@NonNull String key,
boolean hasInitialValue,
@Nullable T initialValue) {
MutableLiveData<T> liveData = (MutableLiveData<T>) mLiveDatas.get(key);
if (liveData != null) {
return liveData;
}
SavingStateLiveData<T> mutableLd;
// double hashing but null is valid value
if (mRegular.containsKey(key)) {
mutableLd = new SavingStateLiveData<>(this, key, (T) mRegular.get(key));
} else if (hasInitialValue) {
mutableLd = new SavingStateLiveData<>(this, key, initialValue);
} else {
mutableLd = new SavingStateLiveData<>(this, key);
}
mLiveDatas.put(key, mutableLd);
return mutableLd;
}
当我们请求一个时,它会创建一个并放入 mLiveDatas
,如果还没有。
显然更好的答案是,我们甚至不需要
savedStateHandle.set(KEY, textLiveData.value)
虽然这是允许的,但当我们设置
textLiveData.value = "Some data"
这已经保存到状态。由于 textLiveData
是从 savedStateHandle
中检索到的,如下所示。
textLiveData = savedStateHandle.getLiveData(KEY)
因此 textLiveData
已经存储在 savedStateHandle
中,对 textLiveData.value
的更改无意中保存在 savedStateHandle
中。
您可以使用 val textLiveData: MutableLiveData<String> = savedStateHandle.getLiveData(KEY)
构造一个 MutableLiveData
并自动保存到 savedInstanceState
。
savedStateHandle.set(KEY, textLiveData)
你不需要这样做,因为 getLiveData
是一个 SavingStateLiveData
,它会自动处理这个。
那是因为你的你class不接受。
您可以输入 Parcelable
或 Serializable
类型。
这是ACCEPTABLE_CLASSES
private static final Class[] ACCEPTABLE_CLASSES = new Class[]{
//baseBundle
boolean.class,
boolean[].class,
double.class,
double[].class,
int.class,
int[].class,
long.class,
long[].class,
String.class,
String[].class,
//bundle
Binder.class,
Bundle.class,
byte.class,
byte[].class,
char.class,
char[].class,
CharSequence.class,
CharSequence[].class,
// type erasure ¯\_(ツ)_/¯, we won't eagerly check elements contents
ArrayList.class,
float.class,
float[].class,
Parcelable.class,
Parcelable[].class,
Serializable.class,
short.class,
short[].class,
SparseArray.class,
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? Size.class : int.class),
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? SizeF.class : int.class),
};