A화면에서 setText를 이용하여 EditText2개와 TextView3개의 필드에 각각의 값들을 입력하고
B화면으로 넘어간 후에 다시 A화면으로 돌아오는 경우가 있었습니다.
이때 EditText에 입력된 값들은 그대로 남아있었지만, TextView에 입력한 값들은 전부 사라지는 경우가 생겼습니다.
각각의 View에 입력하는 값이 전부 달랐기 때문에 2가지 가정을 세웠습니다.
두가지에 대한 테스트를 진행한 결과 모든 데이터가 정상적으로 들어왔고 setText문제도 없었다.
값들의 차이점을 찾아보니 EditText와 TextView의 차이점이 있었다.
View의 내부 상태를 복원할 때, TextView의 text가 초기화되지만 EditText의 text는 유지된다.
그렇다면 두개의 차이점이 무엇일까??
setText의 구현 차이??
상태를 저장하고 복원하는 onSaveInstanceState()에 View속성에 따라 다르게 처리하는 부분이 있는가?
@Override
public void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
} SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
// XXX restore buffer type too, as well as lots of other stuff
if (ss.text != null) {
setText(ss.text);
}
.....
위의 구현을 보면, SavedState
의 text
를 가져와서 setText()
를 호출하고 있다.
그렇다면 TextView
의 text도 복원되어야하는 것은 아닐까?
하지만 TextView
의 text
복원되지 않기 때문에 text==null
이며 onSaveInstanceState()
에서 상태를 저장하지 않는다는 의미이다.
TextView
에서 상태를 저장하지 않는 원인을 찾아보기 위해, onSaveInstanceState()
구현을 살펴보자.
public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); // Save state if we are forced to
**final boolean freezesText = getFreezesText();**
boolean hasSelection = false;
int start = -1;
int end = -1;
if (mText != null) {
start = getSelectionStart();
end = getSelectionEnd();
if (start >= 0 || end >= 0) {
// Or save state if there is a selection
hasSelection = true;
}
}
if (**freezesText** || hasSelection) {
SavedState ss = new SavedState(superState);
if (**freezesText**) {
if (mText instanceof Spanned) {
final Spannable sp = new SpannableStringBuilder(mText);
if (mEditor != null) {
removeMisspelledSpans(sp);
sp.removeSpan(mEditor.mSuggestionRangeSpan);
} ss.text = sp;
} else {
ss.text = mText.toString();
}
}
.....
SavedState
의 text
는 getFreezesText() == true
인 경우에 할당하고 있다.
API 문서에서 설명하고 있는 getFreezesText()
는 아래와 같다.
Return whether this text view is including its entire text contents in frozen icicles. For EditText it always returns true.
또한 freezesText
속성의 설명은 아래와 같다.
If set, the text view will include its current complete text inside of its frozen icicle in addition to meta-data such as the current cursor position. By default this is disabled; it can be useful when the contents of a text view is not stored in a persistent place such as a content provider. For EditText it is always enabled, regardless of the value of the attribute.
EditText의 greezesText속성은 항상 true
이다.
@Override
public boolean getFreezesText() {
return true;
}
결국, EditText
의 getFreezesText()
는 항상 true
를 반환하도록 재정의되어있다.
이로 인해 TextView와는 다르게 text 상태가 보존될 수 있었던 것이다.
TextView
에서도 setFreezesText(Boolean)
또는 freezesText
속성을 true
로 설정한다면
text 상태를 보존할 수 있.다다