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

时间:2015-07-17 08:48:03

标签: android

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

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

@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:

如果我在选择侦听器事件之前插入DoLongTimeOperation(),它是否仍会显示吐司?

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() {
        // ...
    });
}

1 个答案:

答案 0 :(得分:4)

我刚用自己的基本ArrayAdapter运行此代码,并且在创建View并在设置侦听器之前调用setSelection()时立即显示toast(如上所述)。

这绝对不直观,因为您在设置选择后设置了侦听器。了解它的唯一方法是深入了解源代码。在翻找后我发现他们正在向主线程发布this Runnable以通知听众选择更改。这是事件的顺序:

  1. Spinner查看膨胀
  2. 适配器(数据源)设置
  3. 选择集和SelectionNotifier Runnable已发布
  4. 选择侦听器在Spinner上设置
  5. 在mainthread上处理的SelectionNotifier
  6. SelectionNotifier调用onItemSelected()并显示Toast
  7. 发布Runnable以设置您的选择侦听器,以便在第一次传递的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. Spinner查看膨胀
    2. 适配器(数据源)设置
    3. 选择集和SelectionNotifier Runnable已发布
    4. 在Spinner上设置选择侦听器的Runnable已发布
    5. 在mainthread上处理的SelectionNotifier
    6. SelectionNotifier没有通知的侦听器,因此它什么都不做。没有东西显示!
    7. 我们在Spinner上设置Selection侦听器的Runnable在主线程上处理并且设置了选择侦听器