为了活动小家电-保存TextView的状态

84 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的19天,点击查看活动详情

临界点

在A屏,使用setText,在EditText2和TextView3的字段中输入值,
去到B屏​​,出现了又回到A屏的情况。

此时EditText中输入的值保持不变,而TextView中输入的值却全部消失了。

调试

因为输入到每个视图的值都不同,所以做了两个假设。

  1. TextView对应的数据打不进来。
  2. 再次只有 onViewCreated setText 中与 EditText 相关的值。

两者测试结果,所有数据都正常进来,没有setText问题。

寻找值的差异,EditText 和 TextView 之间存在差异。

结论

恢复View内部状态时,TextView的文本被初始化,但EditText的文本保持不变。

那么两者有什么区别呢?


调试

  1. setText 的实现区别??

    1. 结论是没有区别。
      EditText不会覆盖setText() 并按 原样使用TextView 的 setText() 。
  2. 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 也恢复缓冲区类型,以及许多其他的东西
        if (ss.text != null) {
            setText(ss.text);
        }

      .....

SavedState 如果您查看上面的 实现,您 text 正在导入和 setText()调用 .
如果是这样 TextView,''的文本是否也应该恢复?
但是 既然没有  恢复, TextView 也就 意味着它没有把状态保存在 .text``text==null``onSaveInstanceState()

TextView 为了找到没有保存状态的原因, onSaveInstanceState() 让我们看一下实现。

public Parcelable onSaveInstanceState() {   
Parcelable superState = super.onSaveInstanceState();    // 如果我们被迫保存状态
    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) {
           // 或者如果有选择则保存状态
           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();
        }
    }

SavedStateof text 正在 getFreezesText() == true分配 if 。

API 文档 getFreezesText() 中的描述如下。

返回此文本视图是否将其全部文本内容包含在冻结的冰柱中。对于 EditText,它总是返回 true。

此外 freezesText ,属性的描述如下。

如果设置,文本视图将在其冻结的冰柱内包括其当前的完整文本,以及诸如当前光标位置之类的元数据。默认情况下这是禁用的;当文本视图的内容未存储在诸如内容提供者之类的持久位置时,它会很有用。对于 EditText,无论属性的值如何,它始终处于启用状态。

定论

EditText 的 greezesText 属性始终为 true .

 @Override
 public boolean getFreezesText() {
     return true;
 }

毕竟, EditText被 覆盖getFreezesText()总是 true return 。
因此,与 TextView 不同,可以保留文本状态。  如果  将
TextView 属性 设置 为 ,则 可以保留文本状态。setFreezesText(Boolean)``freezesText``true