How to stop onItemSelected() from firing off multiple times after a selection of an item was made?

馋奶兔 提交于 2019-12-24 14:16:39

问题


I've seen another similar thread, but I wasn't able to resolve my issue with the given answers.

EXPLANATION OF MY GOALS:

I have 4 spinners, each has its own ArrayList of strings assigned to it via an adapter. All of these arrays contain the same values at the beginning.

I want to remove the selected value (eg. "item" in spinner1) from all the other spinners (remove "item" from spinner2, 3 and 4) when it is selected.

PROBLEM:

When I select an item for the first two or three times from different spinners (the number of selections needed to reproduce the problem varies) the onItemSelected() method gets called multiple times (the number of callings is greater than the number of actual -user- selections made).

QUESTION:

How to prevent the calling of onItemSelected(); at unnecessary times. I want it to be called only when the actual user makes a selection in one of the spinners and only call it once when that does happen.

If you want to try to help me out and you need more code / images of the problem on the device itself, please, say so.

Here is my whole onItemSelected() method:

@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    if (inCorrection == false)
    {
        s1 = spinner1.getSelectedItemPosition();
        s2 = spinner2.getSelectedItemPosition();
        s3 = spinner3.getSelectedItemPosition();
        s4 = spinner4.getSelectedItemPosition();
        testcount++;
        switch(parent.getId())
        {
            case R.id.v1_q1_s1:
                    if((position != AdapterView.INVALID_POSITION) && (spinner1.getSelectedItem().toString() != "Default---"))
                    {
                        findLists(myList2, myList3, myList4, spinner1.getSelectedItem().toString());
                        if(returnChecks(0) != "Default---")
                        {
                            myList2.add(returnChecks(0)); 
                            myList3.add(returnChecks(0)); 
                            myList4.add(returnChecks(0)); 
                        }
                        addChecks(0, (spinner1.getSelectedItem().toString())); 
                    }
                    else
                    {
                        if(position != AdapterView.INVALID_POSITION)
                        {
                            myList2.add(returnChecks(0)); 
                            myList3.add(returnChecks(0)); 
                            myList4.add(returnChecks(0)); 
                            addChecks(0, (spinner1.getSelectedItem().toString())); 
                        }
                    }
                    adapter1.notifyDataSetChanged();
                    adapter2.notifyDataSetChanged();
                    adapter3.notifyDataSetChanged();
                    adapter4.notifyDataSetChanged();
                    Toast.makeText(Vprasalnik1.this, myList1.toString()+"\n"+myList2.toString()+"\n"+myList3.toString()+"\n"+myList4.toString()+"\n"+checks.toString(), Toast.LENGTH_LONG).show();
                break;
            case R.id.v1_q1_s2:
                if((position != AdapterView.INVALID_POSITION) && (spinner2.getSelectedItem().toString() != "Default---"))
                {
                    findLists(myList1, myList3, myList4, spinner2.getSelectedItem().toString());
                    if(returnChecks(1) != "Default---")
                    {
                        myList1.add(returnChecks(1)); 
                        myList3.add(returnChecks(1)); 
                        myList4.add(returnChecks(1)); 
                    }
                    addChecks(1, (spinner2.getSelectedItem().toString())); 
                }
                else
                {
                    if(position != AdapterView.INVALID_POSITION)
                    {
                        myList1.add(returnChecks(1)); 
                        myList3.add(returnChecks(1)); 
                        myList4.add(returnChecks(1)); 
                        addChecks(1, (spinner2.getSelectedItem().toString())); 
                    }
                }
                adapter1.notifyDataSetChanged();
                adapter2.notifyDataSetChanged();
                adapter3.notifyDataSetChanged();
                adapter4.notifyDataSetChanged();
                Toast.makeText(Vprasalnik1.this, myList1.toString()+"\n"+myList2.toString()+"\n"+myList3.toString()+"\n"+myList4.toString()+"\n"+checks.toString(), Toast.LENGTH_LONG).show();
                break;
            case R.id.v1_q1_s3:
                if((position != AdapterView.INVALID_POSITION) && (spinner3.getSelectedItem().toString() != "Default---"))
                {
                    findLists(myList2, myList1, myList4, spinner3.getSelectedItem().toString());
                    if(returnChecks(2) != "Default---")
                    {
                        myList2.add(returnChecks(2)); 
                        myList1.add(returnChecks(2)); 
                        myList4.add(returnChecks(2)); 
                        Toast.makeText(Vprasalnik1.this, "before: "+returnChecks(2), Toast.LENGTH_LONG).show();
                    }
                    addChecks(2, (spinner3.getSelectedItem().toString())); 
                    Toast.makeText(Vprasalnik1.this, "after: "+returnChecks(2), Toast.LENGTH_LONG).show();
                }
                else
                {
                    if(position != AdapterView.INVALID_POSITION)
                    {
                        myList2.add(returnChecks(2)); 
                        myList1.add(returnChecks(2)); 
                        myList4.add(returnChecks(2)); 
                        addChecks(2, (spinner3.getSelectedItem().toString())); 
                    }
                }
                adapter1.notifyDataSetChanged();
                adapter2.notifyDataSetChanged();
                adapter3.notifyDataSetChanged();
                adapter4.notifyDataSetChanged();
                Toast.makeText(Vprasalnik1.this, myList1.toString()+"\n"+myList2.toString()+"\n"+myList3.toString()+"\n"+myList4.toString()+"\n"+checks.toString(), Toast.LENGTH_LONG).show();
                break;
            case R.id.v1_q1_s4:
                if((position != AdapterView.INVALID_POSITION) && (spinner4.getSelectedItem().toString() != "Default---"))
                {
                    findLists(myList2, myList3, myList1, spinner4.getSelectedItem().toString());
                    if(returnChecks(3) != "Default---")
                    {
                        myList2.add(returnChecks(3)); 
                        myList3.add(returnChecks(3)); 
                        myList1.add(returnChecks(3)); 
                    }
                    addChecks(3, (spinner4.getSelectedItem().toString())); 
                }
                else
                {
                    if(position != AdapterView.INVALID_POSITION)
                    {
                        myList2.add(returnChecks(3)); 
                        myList3.add(returnChecks(3)); 
                        myList1.add(returnChecks(3)); 
                        addChecks(3, (spinner4.getSelectedItem().toString())); 
                    }
                }
                adapter1.notifyDataSetChanged();
                adapter2.notifyDataSetChanged();
                adapter3.notifyDataSetChanged();
                adapter4.notifyDataSetChanged();
                Toast.makeText(Vprasalnik1.this, myList1.toString()+"\n"+myList2.toString()+"\n"+myList3.toString()+"\n"+myList4.toString()+"\n"+checks.toString(), Toast.LENGTH_LONG).show();
                break;
        }
        correctSelection();
    }
}

At the end of the above code there is a function I call named correctSelection();, that corrects the selection of all spinners, because it doesn't work correctly otherwise - it looks like this:

void correctSelection()
{
    inCorrection = true;
    spinner1.setSelection(myList1.lastIndexOf(returnChecks(0)));
    spinner2.setSelection(myList2.lastIndexOf(returnChecks(1)));
    spinner3.setSelection(myList3.lastIndexOf(returnChecks(2)));
    spinner4.setSelection(myList4.lastIndexOf(returnChecks(3)));
    inCorrection = false;
}
/*it sets the position of all spinners to the last "saved"
(current) item selected, so it corrects the possible index offset that occurs otherwise
(returnChecks(); returns the last item selected from an array in a string format)

PS: To avoid the calling of onItemSelected() in case of programmatically setting the selection
of spinners, I've input a boolean flag (variable "inCorrection"), which is set to false before the
selections are made by "the application" and then set back to false when the code gets run.

*/

回答1:


To prevent onItemSelected() from being called when you set up the spinner, you can do it like this:

spinner.setOnItemSelectedListener(null);
adapter.notifyDatasetChanged();
spinner.setSelection(0, false);
spinner.setOnItemSelectedListener(onItemSelectedListener);

Explanation:
The framework fires the onItemSelected event when a change in the selection has occurred. It detects a change by registering the current selected position and the previous selected position (mSelectedPostion and mOldSelectedPosition).

When you call notifyDatasetChanged the framework performs various checks to see if the previous selection can be found, so onItemSelected may or may not be called when the spinner is laid out.

By calling setSelection(0, false) these positions are set to 0, possibly detecting a change, but since onItemSelectedListener is null, onItemSelected wont be fired. Position 0 is selected because I guess the "Default---" value is the first position in the list. You can choose another position if you like.

When the spinner is later laid out there is no change, so onItemSelected wont be fired here either.

Note that this has been established by debugging on API level 19 (Android 4.4 KitKat). I don't know if it works on other versions, and I haven't been able to find anything in the documentation to support it.




回答2:


You can stop the spinner from firing prior to the user making a selection via the optional animation field in the setSelection method. Be sure to order your code this way:

    ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, yourList);
    spinner.setAdapter(spinnerAdapter);    
    spinner.setSelection(0, false);  //stops spinner from firing prior to user selection



回答3:


as explained by user1801374 , I made the fix for my case. Just make sure before and after selection index remains same in order to not to invoke the onItemSelected again.

private int spinnerIndex = 0; 
spinner.setSelection(spinnerIndex, false);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 

    { public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                // Your code here 
               //I was detaching and reattaching one fragment which was calling the onItemSelected multiple times, recursively.
                spinnerIndex = i;
                spinner.setSelection(spinnerIndex, false);
                return;
            }

            public void onNothingSelected(AdapterView<?> adapterView) {
                // Your code here
                return;
            }
}


来源:https://stackoverflow.com/questions/23219652/how-to-stop-onitemselected-from-firing-off-multiple-times-after-a-selection-of

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!