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