我正在夸大一些EditTexts
并将其添加到LinearLayout
:
private void setupCommentViews(){
int i = 0;
Iterator<CommentInformation> iterator = commentInformations.iterator();
while(iterator.hasNext()) {
i++;
View v = LayoutInflater.from(context).inflate(R.layout.comment_row_item, commentsContainer, false);
EditText commentField = (EditText)v.findViewById(R.id.comment);
CommentInformation commentInformation = iterator.next();
final String uniqueId = commentInformation.getUniqueId();
String currentCommentText = comments.get(uniqueId);
if(currentCommentText != null) {
Log.v("into","Setting old text: "+currentCommentText);
commentField.setText(currentCommentText);
} else {
Log.v("into","Setting empty text: "+i);
commentField.setText("Setting empty text: "+i);
}
commentField.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
comments.put(uniqueId, s.toString().trim());
}
});
commentsContainer.addView(v);
}
}
首次运行后的日志如下所示:
04-01 17:40:41.244: V/into(28770): Setting empty text: 1
04-01 17:40:41.254: V/into(28770): Setting empty text: 2
04-01 17:40:41.254: V/into(28770): Setting empty text: 3
所有EditTexts中都包含正确的文本(“设置空文本:#”)
-
我正在向我TextChangedListener
添加EditText
我膨胀的内容,当文本发生变化时,我更新Map<String, String>
并将uniqueId作为键,将注释文本作为值
更改其中一条评论后旋转手机时出现问题。我将评论Map
保存在onSaveInstanceState
:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(COMMENTS, (Serializable)comments);
}
然后我在onActivityCreated
if(savedInstanceState != null) {
Log.v("into","Retrieving...");
comments = (Map<String, String>)savedInstanceState.getSerializable(COMMENTS);
}
我还遍历Map
并验证是否有一个条目包含正确的uniqueId和正确更改的注释文本。
-
接下来,我再次致电setupCommentViews()
。这次日志看起来是正确的,但是EditTexts
ALL与最后一个(最后一个膨胀的文本)具有相同的文本。
04-01 17:42:49.664: V/into(28770): Setting empty text: 1
04-01 17:42:49.664: V/into(28770): Setting old text: Changed the second textview
04-01 17:42:49.674: V/into(28770): Setting empty text: 3
但所有EditTexts
现在都说:“设置空文本:3”
使用ListView
并非我正在寻找的解决方案,因为EditTexts
内有ListView
的{{1}}带有AdjustResize
softInputMode
< / p>
-
任何人都可以了解这里发生的事情吗?
答案 0 :(得分:14)
默认情况下,当调用活动的onSaveInstanceState
方法时,它也会通过视图层次结构并尽可能保存任何视图的状态,并在onRestoreInstanceState
方法时恢复这些视图状态活动稍后调用。当调用每个View来保存状态时,我们可以在View类中看到这个方法:
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
Parcelable state = onSaveInstanceState();
if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
"Derived class did not call super.onSaveInstanceState()");
}
if (state != null) {
// Log.i("View", "Freezing #" + Integer.toHexString(mID)
// + ": " + state);
container.put(mID, state);
}
}
}
EditText继承自TextView,当检查TextView的代码时,我们看到onSaveInstanceState
方法返回当前文本,onRestoreInstanceState
方法返回文本并显示。
现在,回到你的代码。您自己保存文本内容并在调用onCreate
时恢复它,但EditText本身也保存文本并在调用Activity的onRestoreInstanceState
方法时恢复,这在onCreate
之后调用还有一件事,你的所有EditText都有相同的id,所以当视图层次结构被保存到SparseArray时,最后一个EditText状态(在这种情况下是文本内容)将覆盖所有以前的状态。这就是你的问题发生的原因。
<强>解决方案:强>
onRestoreInstanceState
,而不是调用超级方法,这样您就可以阻止视图自动恢复其状态,但我不认为这是个好主意,因为可能还有其他方法默认情况下需要恢复的东西,不仅仅是你的EditText 答案 1 :(得分:1)
EditText根据resId恢复文本。如果您的edittexts没有resIds或者所有人都有相同的resIds,那么您将有恢复问题。
答案 2 :(得分:1)
我遇到了同样的问题。 在我的自定义LinearLayout中,我覆盖了这些方法。
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
return new SavedState(superState, txtData.getText().toString());
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
txtData.setText(savedState.data);
}
@Override
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
super.dispatchFreezeSelfOnly(container);
}
@Override
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
super.dispatchThawSelfOnly(container);
}
private class SavedState extends BaseSavedState {
public final Creator<SavedState> CREATOR = new Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
private String data;
public SavedState(Parcel source) {
super(source);
data = source.readString();
}
public SavedState(Parcelable superState, String data) {
super(superState);
this.data = data;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(data);
}
}
希望这有帮助。
答案 3 :(得分:0)
我也遇到了这个问题,但是我必须先恢复状态。因此,我创建了一个名为FixedEditText
的视图,并同时覆盖了dispatchSaveInstanceState()
和dispatchRestoreInstanceState()
两种方法。就像这样:
override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
try {
val key = initKey()
if (key != null && isSaveEnabled) {
val state = onSaveInstanceState()
if (state != null) {
//don't use the id as the key
container.put(key.hashCode(), state)
}
}
} catch (e: Exception) {
super.dispatchSaveInstanceState(container)
e.printStackTrace()
}
}
override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) {
try {
val key = initKey()
if (key != null) {
val state = container.get(key.hashCode())
if (state != null) {
onRestoreInstanceState(state)
}
}
} catch (e: Exception) {
super.dispatchRestoreInstanceState(container)
e.printStackTrace()
}
}
private fun initKey(): Any? {
(parent as? View)?.run {
//My ViewGroup has diff id.
return "${this.javaClass.simpleName}$${this.id}"
}
return null
}