为什么即使事件setOnItemSelectedListener在setSelection之后,Spinner控件仍然显示提示信息?

我在spinnerRanger.setSelection之后编写了Spinner的事件setOnItemSelectedListener。

我认为Toast.makeText(...)在我第一次运行APP时不会启动,但提示信息仍然显示,为什么?

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.cleanup_delete_fragment_old, container, false); mView = rootView; mContext = rootView.getContext(); InitValueOfControls(); return rootView; } private void InitValueOfControls() { spinnerRanger = (Spinner)mView.findViewById(R.id.spinner); PublicParFun.FillRangeSpinner(mView, spinnerRanger); spinnerRanger.setSelection(PublicParFun.GetIndexOfRangeDeleteOld(mContext)); spinnerRanger.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(mContext, "My "+position, Toast.LENGTH_LONG).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } 

致Trevor Carothers:

如果我在select侦听器事件之前插入一个DoLongTimeOperation() ,它是否仍然显示Toast?

 private void InitValueOfControls() { spinnerRanger = (Spinner)mView.findViewById(R.id.spinner); PublicParFun.FillRangeSpinner(mView, spinnerRanger); spinnerRanger.setSelection(PublicParFun.GetIndexOfRangeDeleteOld(mContext)); DoLongTimeOperation(); spinnerRanger.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(mContext, "My " + position, Toast.LENGTH_LONG).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } 

代码A:

 private void InitValueOfControls() { spinnerRanger = (Spinner)mView.findViewById(R.id.spinner); PublicParFun.FillRangeSpinner(mView, spinnerRanger); spinnerRanger.setSelection(PublicParFun.GetIndexOfRangeDeleteOld(mContext)); DoLongTimeOperation(); spinnerRanger.post(new Runnable() { @Override public void run() { spinnerRanger.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(mContext, "My "+position, Toast.LENGTH_LONG).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } }); } 

代码B

 private void InitValueOfControls() { spinnerRanger = (Spinner)mView.findViewById(R.id.spinner); PublicParFun.FillRangeSpinner(mView, spinnerRanger); spinnerRanger.setSelection(PublicParFun.GetIndexOfRangeDeleteOld(mContext)); spinnerRanger.post(new Runnable() { @Override public void run() { spinnerRanger.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { // ... } } }); } 

代码C

 private void InitValueOfControls() { spinnerRanger = (Spinner)mView.findViewById(R.id.spinner); PublicParFun.FillRangeSpinner(mView, spinnerRanger); spinnerRanger.setSelection(PublicParFun.GetIndexOfRangeDeleteOld(mContext)); spinnerRanger.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { // ... }); } 

Solutions Collecting From Web of "为什么即使事件setOnItemSelectedListener在setSelection之后,Spinner控件仍然显示提示信息?"

我刚刚使用自己的基本ArrayAdapter运行这个代码,并且在创buildView时立即显示敬酒,并且在侦听器被设置之前调用setSelection()(如上所述)。

这绝对是不直观的,因为你设置了select后的监听器。 要深入了解底层的唯一方法就是深入了解源代码。 在翻译后,我发现他们发布这个Runnable到主线程来通知监听器select的变化。 这是事件的顺序:

  1. 微调视图膨胀
  2. 适配器(数据源)设置
  3. select集和SelectionNotifier Runnable已过帐
  4. select监听器在Spinner上设置
  5. 在mainthread上处理的SelectionNotifier
  6. SelectionNotifier会显示onItemSelected()和Toast

发布一个Runnable来设置您的select监听器,以便在第一次传递的SelectionNotifier之后处理它:

 private void InitValueOfControls() { spinnerRanger=(Spinner)mView.findViewById(R.id.spinner); PublicParFun.FillRangeSpinner(mView, spinnerRanger); spinnerRanger.setSelection(PublicParFun.GetIndexOfRangeDeleteOld(mContext)); spinnerRanger.post(new Runnable() { @Override public void run() { spinnerRanger.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {...} } }); } 

事件的新秩序是:

  1. 微调视图膨胀
  2. 适配器(数据源)设置
  3. select集和SelectionNotifier Runnable已过帐
  4. 可运行以在Spinner上设置select监听器
  5. 在mainthread上处理的SelectionNotifier
  6. SelectionNotifier没有监听器来通知,所以它什么都不做。 没有显示!
  7. 我们在Spinner上设置select监听器的Runnable在主线程上处理,select监听器被设置