简体   繁体   中英

Android ListPreference don't save the selection

i show a selectable list with all launchable installed apps. I wan't to save the selections, but the ListPreference saved all listed entries.

Where is my mistake?

Here is my ListPreference:

public class SettingsSelectsApps extends ListPreference {

private String separator;
private static final String DEFAULT_SEPARATOR = "\u0001\u0007\u001D\u0007\u0001";
private boolean[] entryChecked;

public SettingsSelectsApps(Context context, AttributeSet attributeSet) {
    super(context, attributeSet);
    loadEntries();
    entryChecked = new boolean[getEntries().length];
    separator = DEFAULT_SEPARATOR;
}

public SettingsSelectsApps(Context context) {
    this(context, null);
}

private void loadEntries() {

    final Context context = getContext();

    final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

    final List<ResolveInfo> pkgAppsList = context.getPackageManager().queryIntentActivities( mainIntent, 0);

    CharSequence[] entries = new CharSequence[pkgAppsList.size()];
    CharSequence[] entryValues = new CharSequence[pkgAppsList.size()]; 

    int j = 0;

    for ( ResolveInfo P : pkgAppsList ) {
        entryValues[j] = (CharSequence) P.getClass().getName();
        entries[j] = P.loadLabel(context.getPackageManager());
        ++j;
    };

    setEntries(entries);
    setEntryValues(entryValues);
}

@Override
protected void onPrepareDialogBuilder(Builder builder) {
    CharSequence[] entries = getEntries();
    CharSequence[] entryValues = getEntryValues();       

    if (entries == null || entryValues == null || entries.length != entryValues.length) {
        throw new IllegalStateException(
                "MultiSelectListPreference requires an entries array and an entryValues "
                        + "array which are both the same length");
    }

    restoreCheckedEntries();
    OnMultiChoiceClickListener listener = new DialogInterface.OnMultiChoiceClickListener() {
        public void onClick(DialogInterface dialog, int which, boolean val) {
            entryChecked[which] = val;
        }
    };
    builder.setMultiChoiceItems(entries, entryChecked, listener);
}

private CharSequence[] unpack(CharSequence val) {
    if (val == null || "".equals(val)) {
        return new CharSequence[0];
    } else {
        return ((String) val).split(separator);
    }
}

public CharSequence[] getCheckedValues() {
    return unpack(getValue());
}

private void restoreCheckedEntries() {
    CharSequence[] entryValues = getEntryValues();
    CharSequence[] vals = unpack(getValue());

    if (vals != null) {
        List<CharSequence> valuesList = Arrays.asList(vals);
        for (int i = 0; i < entryValues.length; i++) {
            CharSequence entry = entryValues[i];
            entryChecked[i] = valuesList.contains(entry);
        }
    }

    SharedPreferences prefs = getSharedPreferences();
    try{
      Map<String,?> keys = prefs.getAll();

        for(Map.Entry<String,?> entry : keys.entrySet()){          
         }
    } catch(NullPointerException e) {
        Log.d("map values","Error: "+e);
    }
}

@Override
protected void onDialogClosed(boolean positiveResult) {
    List<CharSequence> values = new ArrayList<CharSequence>();

    CharSequence[] entryValues = getEntryValues();
    if (positiveResult && entryValues != null) {
        for (int i = 0; i < entryValues.length; i++) {
            if (entryChecked[i] == true) {
                String val = (String) entryValues[i];
                values.add(val);
            }
        }

        String value = join(values, separator);
        setSummary(prepareSummary(values));
        setValueAndEvent(value);
    }
}

private void setValueAndEvent(String value) {
    if (callChangeListener(unpack(value))) {
        setValue(value);
    }
}

private CharSequence prepareSummary(List<CharSequence> joined) {
    List<String> titles = new ArrayList<String>();
    CharSequence[] entryTitle = getEntries();
    CharSequence[] entryValues = getEntryValues();
    int ix = 0;
    for (CharSequence value : entryValues) {
        if (joined.contains(value)) {
            titles.add((String) entryTitle[ix]);
        }
        ix += 1;
    }
    return join(titles, ", ");
}

@Override
protected Object onGetDefaultValue(TypedArray typedArray, int index) {
    return typedArray.getTextArray(index);
}

@Override
protected void onSetInitialValue(boolean restoreValue,
        Object rawDefaultValue) {
    String value = null;
    CharSequence[] defaultValue;
    if (rawDefaultValue == null) {
        defaultValue = new CharSequence[0];
    } else {
        defaultValue = (CharSequence[]) rawDefaultValue;
    }
    List<CharSequence> joined = Arrays.asList(defaultValue);
    String joinedDefaultValue = join(joined, separator);
    if (restoreValue) {
        value = getPersistedString(joinedDefaultValue);
    } else {
        value = joinedDefaultValue;
    }

    setSummary(prepareSummary(Arrays.asList(unpack(value))));
    setValueAndEvent(value);
}

protected static String join(Iterable<?> iterable, String separator) {
    Iterator<?> oIter;
    if (iterable == null || (!(oIter = iterable.iterator()).hasNext()))
        return "";
    StringBuilder oBuilder = new StringBuilder(String.valueOf(oIter.next()));
    while (oIter.hasNext())
        oBuilder.append(separator).append(oIter.next());
    return oBuilder.toString();
}

}

I believe you use code from this gist which works great except for the separator. I don't know why did the author choose the separator to be "\\\\\" .

Once I tried to change the separator to any other string, for example ",," everything worked.

The separator string chosen seems to cause android to be unable to parse the shared preferences xml document.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM