Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking two NumberPicker views with onValueChanged causes unpredictable crashes

Tags:

android

I've created a dialog containing two NumberPicker views. The first contains a list of groups, the second contains the items from the selected group:

Group         Group Items
  1            2: Group 2 Item 2
 [2]          [3: Group 2 Item 3]
  3            4: Group 2 Item 4

I'm hooking in to the setOnValueChangedListener in the first NumberPicker to populate the second NumberPicker.

  mNumberPickerGroup.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
        @Override
        public void onValueChange(NumberPicker numberPicker, int from, int to) {
            int size = mData.getItemsForGroup(to).size();
            String[] strings = mData.getItemTitlesForGroup(to);

            mNumberPickerItems.setMinValue(1);
            mNumberPickerItems.setValue(1);

            mNumberPickerItems.setMaxValue(size);
            mNumberPickerItems.setDisplayedValues(strings);

        }
    });

This basically works - until, in certain circumstances, changing the group a few times can cause a crash in the NumberPicker class, when setting the setDisplayedValues strings.

The error is an array index out of bounds exception in the numberpicker for items, a line to do with the string array I passed in. I've set a break point in the update code above, and verified that the String array is always the correct size for the number of items set between min and max value on the number picker, so this has stumped me.

  java.lang.ArrayIndexOutOfBoundsException: length=22; index=22
        at android.widget.NumberPicker.ensureCachedScrollSelectorValue(NumberPicker.java:1768)
        at android.widget.NumberPicker.initializeSelectorWheelIndices(NumberPicker.java:1583)
        at android.widget.NumberPicker.setMaxValue(NumberPicker.java:1390)
        at uk.co.my.app.fragments.GroupMarkUptoDialog.updateItemPicker(MarkUptoDialog.java:99)

I'm about to start reading through what happens in the NumberPicker to figure out if I'm using it wrong, but any suggestions would be welcome. "ensureCachedScrollSelectorValue" makes me think I need to reset the numberpicker somehow before updating it with new data but I'm not sure.

Can anyone see what I'm doing wrong here?

I realise the NumberPicker is not really a String picker, so if anyone has a better suggestion for how to achieve this sort of UI I'm all ears. Otherwise, I'm heading down the route of trying to implement some kind of debouncer, to update the items picker once all activity on the group picker is complete.

like image 478
Shaun Avatar asked Jun 10 '14 11:06

Shaun


2 Answers

It happens when you setDisplayedValue(String[]) many times.

If the string[]'s length is larger than the current getMaxValue(), Exception happens!

My solution

use

picker.setMaxValue(0);

before

picker.setDisplayedValues(stringArr);

My code

cityPicker.setMaxValue(0);
    try {
        cityPicker.setDisplayedValues(citySet.toArray(new String[citySet.size()]));
    } catch (Exception e) {
        Log.e("Ninja", "cityPicker.setDisplayedValues(citys) occurs Error. province is " + province);
    }
    cityPicker.setMaxValue(citySet.size() - 1);
like image 85
Ninja Avatar answered Nov 14 '22 22:11

Ninja


If you use indexes started from 1 then use:

        int size = mData.getItemsForGroup(to-1).size();

Use this to change second picker (if current value is above maximum it will set it to new maximum):

        int i = mNumberPickerItems.getValue();
        int max = strings.length;
        if (i > max)
            i = max;
        mNumberPickerItems.setMinValue(1);
        mNumberPickerItems.setMaxValue(1);
        mNumberPickerItems.setDisplayedValues(strings);
        mNumberPickerItems.setMaxValue(max);
        mNumberPickerItems.setValue(i);

And try to use values as indexes, i.e.

        minValue=0 
        maxValue=strings.length-1
like image 21
Borzh Avatar answered Nov 14 '22 23:11

Borzh