今天使用spinner时引发了一个崩溃大坑,debug了一会依然不知所以,翻看了源码才发现症结所在。故此记录一下。
spinner设置了spinnerMode为dropdown(默认也是dropdown),此时假如是自定义adapter,需要特别注意adapter的实现方式。
因adapter需要实现SpinnerAdapter接口,这里有两个方法getDropDownView和getView,关于这两个的区别网上一般认为getView 设置的是Spinner下拉打开前的布局,getDropDownView 设置的是下拉打开后,下拉的布局。这个说法含糊不清,实际上看源码可知这两个是有关联的。
AppCompatSpinner源码片段:
@Override
public void setAdapter(SpinnerAdapter adapter) {
// The super constructor may call setAdapter before we're prepared.
// Postpone doing anything until we've finished construction.
if (!mPopupSet) {
mTempAdapter = adapter;
return;
}
super.setAdapter(adapter);
if (mPopup != null) {
final Context popupContext = mPopupContext == null ? getContext() : mPopupContext;
mPopup.setAdapter(new DropDownAdapter(adapter, popupContext.getTheme()));
}
}
可以看出当mPopup!=null时,设置的adapter为DropDownAdapter,跟踪DropDownAdapter看下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getDropDownView(position, convertView, parent);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return (mAdapter == null) ? null
: mAdapter.getDropDownView(position, convertView, parent);
}
可以看到getView方法最终还是调用了getDropDownView方法。因此如果spinner的spinnerMode为dropdown,在自定义adapter时一定要记得重写getDropDownView方法,否则getView就会取到null值,从而引发闪退血案。