Android 如何保留实例状态恢复机制覆盖的值?
在我的应用程序中,我有一个Android 如何保留实例状态恢复机制覆盖的值?,android,Android,在我的应用程序中,我有一个微调器,它的onItemSelected将类成员的值(例如a)初始化为其默认值0。然后,用户可以执行步骤更改a的值。我正在onSaveInstanceState中保存a的值,并在onRestoreInstanceState中还原它。但是,显然,由于恢复了微调器,它的onItemSelected会被调用,并将a恢复为零。我希望保留用户输入的值 但是,请注意,a的旧值在微调器的任何其他设置中都没有意义(因此在项目选择时将其归零)。不幸的是,也很难验证它。因此,在不知道对on
微调器
,它的onItemSelected
将类成员的值(例如a
)初始化为其默认值0
。然后,用户可以执行步骤更改a
的值。我正在onSaveInstanceState
中保存a
的值,并在onRestoreInstanceState
中还原它。但是,显然,由于恢复了微调器
,它的onItemSelected
会被调用,并将a
恢复为零。我希望保留用户输入的值
但是,请注意,a
的旧值在微调器的任何其他设置中都没有意义(因此在项目选择时将其归零)。不幸的是,也很难验证它。因此,在不知道对onItemSelected
的调用是假的情况下,将a
置零是不可避免的
问题是,输入事件处理程序似乎被放入某个队列中,并在onCreate
/onRestoreInstanceState
完成后调用(两次,这是另一件我不理解的事情)。因此,我的问题是,我应该在什么时候将a
从保存的实例状态恢复为非默认值?我是否应该以某种方式将此任务放在输入事件队列的末尾?或者,是否有一种方法可以区分调用onItemSelected
是由于实际用户输入还是只是实例状态恢复而发生的
代码示例:
private String KEY = "(...).A";
private int a;
public void onItemSelected(AdapterView<?> parentView, View childView, int position, long id) {
/* other important stuff */
a = 0;
Log.d("info", "a zeroed");
}
public void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putInt(KEY, a);
}
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
a = state.getInt(KEY, a);
Log.d("info", "a restored");
}
private boolean trigger=false;
已选择公共视图(AdapterView父视图、View子视图、int位置、长id){
如果(触发器){
a=0;
Log.d(“信息”,“a归零”);
}else-trigger=true;
}
这看起来是最简单的解决方案我必须承认,我并没有完全按照您在问题中所说的去做,但是恢复微调器的选择非常简单:
在您的onItemSelected()
中,使用:a=position
在onRestoreInstanceState()的末尾调用spinner.setSelection(a)代码>
请理解,每次微调器更改其选择时,微调器都会调用onItemSelected()
,包括内部的onRestoreInstanceState()
。但是,由于将a
设置为当前选择,因此这不是问题 以下是我到目前为止的想法。它在不计算仅通过观察发现的onItemSelected
的两个调用的情况下完成了这一技巧。但是,我仍然认为这是一个解决办法:
private String KEY = "(...).A";
private String SEL = "(...).SEL";
private int a;
private int sel = -1;
public void onItemSelected(AdapterView<?> parentView, View childView, int position, long id) {
/* other important stuff */
if(position != sel) {
a = 0;
Log.d("info", "a zeroed");
sel = position;
} else
Log.d("info", "a kept");
}
public void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putInt(KEY, a);
state.putInt(SEL, sel);
}
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
a = state.getInt(KEY);
sel = state.getInt(SEL);
Log.d("info", "a restored");
}
此解决方案的缺点是,a
在微调器仍然未初始化时具有其值,这在当时不会导致问题,但永远不会发生。一个合适的解决方案应该让onimselected
完成它的所有工作,然后设置A
。对不起,我不清楚<代码>a
不是所选项目的位置,而是一些其他数据。为了减少混淆,现在让a
成为一个字符串。假设在微调器的位置0
,用户在其中输入一些英文文本,在1
中输入德语文本。我想避免a
中的文本是德语,而微调器显示“英语”的情况,因此每当语言发生变化时,我都会删除文本。但是,状态恢复的作用也类似于更改,即删除我的文本,即使它使用的语言正确。如果您只想忽略对onItemSelected()
(状态恢复时)的第一次调用,请使用布尔值忽略第一次调用。请看Johnny Doe的答案。它实际上被调用了两次(onCreate
和onRestore…
,可能是??),所以我需要忽略这两个。不过,我不知道这是否是一条规则。我对@Johnny Doe关于为什么这不起作用的回答做了更详细的评论。奇怪的是,它被调用了两次,但我无法在没有看到您的代码的情况下猜测为什么会发生这种情况。但是,您可以轻松地使用整数跳过前两次调用onItemSelected()
。很抱歉,我无法使用此解决方案。函数已经在一行中被调用了两次,尽管两次调用都使用了还原的值(见上文)。所以我必须用触发器一直数到2
。由于我不知道为什么会发生这种情况,我不能确定它是否特定于我的版本或环境-同一个函数很可能在不同的设备上调用三次或一次,我的触发器将无法工作。
private boolean trigger = false;
public void onItemSelected(AdapterView<?> parentView, View childView, int position, long id) {
if (trigger){
a = 0;
Log.d("info", "a zeroed");
} else trigger = true;
}
private String KEY = "(...).A";
private String SEL = "(...).SEL";
private int a;
private int sel = -1;
public void onItemSelected(AdapterView<?> parentView, View childView, int position, long id) {
/* other important stuff */
if(position != sel) {
a = 0;
Log.d("info", "a zeroed");
sel = position;
} else
Log.d("info", "a kept");
}
public void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putInt(KEY, a);
state.putInt(SEL, sel);
}
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
a = state.getInt(KEY);
sel = state.getInt(SEL);
Log.d("info", "a restored");
}
info a restored
info a kept
info a kept