Sunday 27 April 2014

ListPreference: how to load data dinamically

In this tutorial I'll explain how to populate a ListPreference programmatically. It is easier than you might expect; however I haven't found any official tutorial about it. If you need more information about Settings in Android you can read the official documentation.


Generally speaking, if you want to add a ListPreference to your app's settings, you have to add a ListPreference object in the preference XML file, like in the following example:
<ListPreference
        android:dependency="pref_sync"
        android:key="pref_syncConnectionType"
        android:title="@string/pref_syncConnectionType"
        android:dialogTitle="@string/pref_syncConnectionType"
        android:entries="@array/pref_syncConnectionTypes_entries"
        android:entryValues="@array/pref_syncConnectionTypes_values"
        android:defaultValue="@string/pref_syncConnectionTypes_default" />

As you can see you provide the entries of the ListPreference, and the corresponding values, with the items android:entries and android:entryValues, that refer to an array loaded in the res/values folder.
But if you want to load the data programmatically (for example, if you want to fetch the data from a local database or from an online service), you must create a custom ListPreference class.

To begin with, let's see the new preference XML file with a reference to our custom ListPreference:
<com.androidthetechnicalblog.preference.MyCustomPreference
            android:key="pref_mycustompreference"
            android:title="@string/pref_mycustompreference"
            android:summary="@string/pref_mycustompreference_summary"/>

We are creating a custom ListPreference class, so we must provide the full path of the class. As you can also see, we omitted android:entries and android:entryValues, because we want to load the data programmatically.

Now let's see how MyCustomPreference class looks like (not relevant code omitted for brevity):
public class MyCustomPreference extends ListPreference {  
    // ...  

    public MyCustomPreference (Context context, AttributeSet attrs) {      
        super(context, attrs);      
    
        setEntries(entries());         
        setEntryValues(entryValues());         
        setValueIndex(initializeIndex());       
    }  

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

    private CharSequence[] entries() {      
        //action to provide entry data in char sequence array for list          
        String myEntries[] = {"one", "two", "three", "four", "five"};         

        return myEntries;  
    }  

    private CharSequence[] entryValues() {      
        //action to provide value data for list           
     
        String myEntryValues[] = {"ten", "twenty", "thirty", "forty", "fifty"};
        return myEntryValues;
   }

   private int initializeIndex() {
        //here you can provide the value to set (typically retrieved from the SharedPreferences)
        //...

        int i = 2;
        return i;
    }
}

The code is quite simple. You just have to provide the entries and entryValues through the methods setEntries and setEntryValues, that accept a CharSequence (or String) array as a parameter. You can also set the default initial value, typically retrieved from the SharedPreferences, through the method setValueIndex

For everything that is not explicitly covered in this tutorial you can refer to the official documentation aboud Android settings.

2 comments: