EditText在屏幕方向改变时不会自动保存

13

我看到安卓系统在应用即将被停止或关闭时会自动保存EditText对象的内容。然而,在我的应用中,当屏幕方向改变时,EditText的内容会丢失。

这是正常行为吗?那么我需要使用onSaveInstanceState/onRestoreInstanceState手动保存/恢复它的内容吗?还是有更简单的方法告诉安卓系统保存并恢复它?

编辑:

我在代码中动态创建了EditText对象,而不是在XML中创建。这与问题有关(请参见下面的接受答案)。

5个回答

29

这不是正常的行为。

首先,请确保您在布局XML中为您的EditText控件分配了ID。

编辑1:它只需要一个ID,无论如何。如果您是通过编程方式执行此操作,则除非具有ID,否则它将失去状态。

因此,以此作为快速而简单的示例:

    // Find my layout
    LinearLayout mLinearLayout = (LinearLayout) findViewById(R.id.ll1);
    // Add a new EditText with default text of "test"
    EditText testText = new EditText(this.getApplicationContext());
    testText.setText("test");


    // This line is the key; without it, any additional text changes will 
    // be lost on rotation. Try it with and without the setId, text will revert
    // to just "test" when you rotate.

    testText.setId(100); 

    // Add your new EditText to the view.
    mLinearLayout.addView(testText);

那将解决你的问题。

如果那行不通,你需要自己保存和恢复状态。

像这样重写onSaveInstanceState

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("textKey", mEditText.getText().toString());
}

然后在 OnCreate 中进行恢复:

public void onCreate(Bundle savedInstanceState) {
    if(savedInstanceState != null)
    {
        mEditText.setText(savedInstanceState.getString("textKey"));
    }
}

另外,请不要使用android:configChanges="orientation"来尝试完成此操作,这是错误的做法。


谢谢。我正在使用Java(以编程方式)创建此editText,而不是在XML中创建。因此,editText没有XML ID。这可能是原因吗?Android不会保存已经以编程方式创建的视图吗?但它确实保存了一个同样是以编程方式创建的radioGroup的状态。奇怪。 - Luis Mendo
抱歉对混淆感到不满:radioGroup状态实际上是通过我的一些代码(保存和检索应用程序首选项)进行保存的,而不是由系统保存。我已经删除了该代码并检查了系统也没有保存该视图的状态。因此,这就是原因:通过编程创建的视图没有XML ID,因此不会自动保存。你觉得呢?这有道理吗? - Luis Mendo
只需要一个ID,就可以了!请查看我的编辑,如果有效,请接受答案。 :) - Mike P.
1
问题已解决,谢谢!我不知道如何在Java中分配ID。 - Luis Mendo
创建一个静态属性 static int testTextId = View.generateViewId(),然后在 testText.setId(ClassName.testTextId) 中使用它。这样你就不必发明一个硬编码的ID整数了。 - Ted Henry

2
我发现在 onSaveInstanceState 中保存对象的最简单方法是实现 Serializable 并将其放入 bundle。
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("myObj", myObj);
}

在我的对象类实现了Serializable接口并且在onCreate()方法中:

if (savedInstanceState != null && savedInstanceState.getSerializable("myObj") != null) {
myObj = ((MyObj) savedInstanceState.getSerializable("myObj"));
}

1
谢谢。实际上我想让Android为我完成这个任务。结果发现给对象分配一个ID就足以让Android完成工作(请参见Mike P.的答案)。 - Luis Mendo

2

可能的原因之一是你重写了onSaveInstanceState方法,但忘记调用父类的同名方法。

super.onSaveInstanceState(outState);

活动中所有视图的状态都会自动保存,除非你覆盖了此功能。即使这很明显,也有可能犯错误。


其实我的问题是对象没有ID,因为我是在Java中创建它,而不是在XML中。但还是谢谢你的想法,对其他人可能有用。 - Luis Mendo

2
你能在xml布局中使用android:freezesText="true"吗?

谢谢您的建议。我是在Java中创建editText,而不是在XML中。我尝试了editText.setFreezesText(true);但它没有起作用。 - Luis Mendo
3
这段话有些微妙,但您只需在TextView中使用freezesText,而不是在EditText中使用。Android似乎只会保存可能会更改的项的状态;EditText被设计为可编辑,所以只要有ID,Android就会在软关闭时保存其状态(尽管不是在硬退出时)。 TextView则相反,因此有必要明确地保持其状态(如果需要的话)。 - Mike P.

2

编辑文本只需要有一个唯一标识符。如果您动态添加编辑文本,请确保没有相同的ID,否则可能会导致无法恢复文本。 同样,如果您在xml中添加,请使用唯一的ID。希望这能帮助某些人。

顺便说一下:EditText默认情况下设置为setFreezesText为true。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接