Android Can';旋转屏幕后找不到旋转器

Android Can';旋转屏幕后找不到旋转器,android,android-layout,listview,android-fragments,Android,Android Layout,Listview,Android Fragments,我使用“Fragment”获得一个包含两个“Fragment”的布局,因此我的类扩展了“Fragment” 我在左边的“片段”上加载一个“列表视图”,在右边的“片段”上加载另一个修改过的“列表视图”。在这里,我有一个“旋转器”,我必须改变它的颜色 我有以下代码: private void loadSpinner(int value) { //Not relevant code adapter = new ArrayAdapter<CharSequence>(getA

我使用“Fragment”获得一个包含两个“Fragment”的布局,因此我的类扩展了“Fragment”

我在左边的“片段”上加载一个“列表视图”,在右边的“片段”上加载另一个修改过的“列表视图”。在这里,我有一个“旋转器”,我必须改变它的颜色

我有以下代码:

private void loadSpinner(int value) {
    //Not relevant code

    adapter = new ArrayAdapter<CharSequence>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_item, data);

    adapter.setDropDownViewResource(R.layout.spinner);

    spinner.setAdapter(adapter);
}

@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    String value = parent.getItemAtPosition(position).toString();

   ((TextView) parent.getChildAt(0)).setTextColor(getResources().getColor(R.color.black));

  //Some code
}
private void loadSpinner(int值){
//非相关代码
adapter=new ArrayAdapter(getActivity().getApplicationContext(),android.R.layout.simple\u微调器\u项,数据);
adapter.setDropDownViewResource(R.layout.spinner);
旋转器。设置适配器(适配器);
}
@凌驾
已选择公共视图(AdapterView父视图、视图视图、整型位置、长id){
字符串值=parent.getItemAtPosition(position).toString();
((TextView)parent.getChildAt(0)).setTextColor(getResources().getColor(R.color.black));
//一些代码
}
在我旋转设备屏幕之前,上面的代码按预期工作。在这里,我在
((TextView)parent.getChildAt(0)).setTextColor(getResources().getColor(R.color.black))得到一个
nullpointerexception

如果我对上述行进行注释,因为我在旋转屏幕之前保存状态,所以在旋转屏幕之后,我的数据将恢复,并且所有工作都按预期进行,除了处于浅色的微调器,因此可见性差


我知道我可以创建自己的“微调器”布局并解决此问题,但我想知道如何解决此问题。

屏幕旋转后,您的
微调器
视图尚未附加任何子视图(您可以通过调用
parent.getChildCount()
进行验证),因此您的
parent.getChildAt(0)
返回空值,导致
NPE

解释 创建活动后,Android通过为布局层次结构中的每个视图调用
onMeasure()
,然后调用
onLayout()
来显示其内容。

Spinner
将在调用
onLayout()
的过程中创建其子视图,并使用适配器中的数据填充这些子视图,尽可能附加这些子视图。

因此,通常情况下,对于微调器,您将有序列:
onMeasure
->
onLayout
->
onimselected

而且,由于在选择
onlineout
之前调用了
onlineout
,所以在初始活动启动期间,一切都很好

现在,让我们看看旋转屏幕时会发生什么:

在销毁活动之前,将调用它的
onSavedInstanceState
,它将调用传播到
微调器的
onSavedInstanceState
,该微调器将保存当前选定的位置

旋转后,将重新创建活动,然后调用其
onRestoreInstanceState

当调用Activity#
onRestoreInstanceState
时,它最终将调用Spinner's,其代码如下:

    SavedState ss = (SavedState) state;
    //...some code
    if (ss.selectedId >= 0) {
        mDataChanged = true;
        //...some more code
    }
如您所见,若微调器的上一个状态是使用保存的,它将始终设置mDataChanged标志

然后调用,它具有以下代码段:

    if (mDataChanged) {
        handleDataChanged();
    }
()的实现最终将调用(),触发Spinner的
onItemSelected

因此在
onMeasure
期间,在
onLayout
之前调用
onimselected

如上所述,
Spinner
在调用其
onLayout
之前没有子项

希望问题现在清楚了

变通办法 要确认该行为并解决NPE,您只需在活动中为
onSavedInstanceState
/
onRestoreInstanceState
提供空实现即可(无需调用超级实现):

这将阻止设置
mDataChanged
,并且
onMeasure
不会触发
fireOnSelected

附加说明 不调用“活动”
super。
在覆盖SavedInstanceState
/
onRestoreInstanceState
时,绝对不建议执行,因为至少您将无法自动保存内部视图(包括微调器)的状态。
我鼓励您这样做只是为了验证上面解释的行为,并查看
NPE
是否消失


更好的解决方案是在.xml布局中为微调器项定义所需颜色的
TextView
,并使用它为微调器构建
ArrayAdapter

从何处调用
loadSpinner
?@Szymon Hi。在
onCreateView
我正在做这个
spinner=(spinner)itemDataLayout.findviewbyd(R.id.availableValues);spinner.setOnItemSelectedListener(此)和微调器从,想象一下,
functionX
加载。当我单击左侧
列表视图
上的项目时,调用函数
functionX
。如果我来自一个
savedrestoredstate
,则会从
onStart()
调用
functionX
,您可能在调用
loadSpinner
之前触发了
onItemSelected
,这将设置适配器。您可以通过将断点放在选中的
onimselected
和第行
spinner.setAdapter()
中来验证顺序,并查看在rotation@Favolas如果我在前面的评论中所写的是这种情况,那么您将始终在
onItemSelected
中选择NPE,因为spinner尚未显示任何子项。所以,你有两个选择来解决这个问题,但首先你需要检查情况是否如此。@kiruwka-Nop
loadSpinner
是第一位的,非常感谢您的解释。你是对的。“要实现我的自定义微调器了。”法沃拉斯很高兴它起了作用。请考虑接受。新年快乐!嘿..我遇到了同样的问题..我实现了我的自定义微调器..仍然得到相同的
nullpointerexception
。您是否使用自定义微调器或其他方法解决了此问题?我在@Favolas解决了它,您的
@Override 
protected void onSaveInstanceState(Bundle outState) { /* do nothing */ }