code: @Override
  	public View getView(int position, View convertView, ViewGroup parent) {
  		ViewHolder holder;
  		Pair<String, ?> keyVal = getItem(position);
  		if (convertView == null) {
  			holder = new ViewHolder();
  			convertView = inflater.inflate(R.layout.preference_item, parent, false);
  			holder.key = (TextView) convertView.findViewById(R.id.key);
  			holder.value = (TextView) convertView.findViewById(R.id.value);
  			convertView.setTag(holder);
  		} else {
  			holder = (ViewHolder) convertView.getTag();
  		}
  
          holder.key.setText(keyVal.first);
          String value = "";
          Object second = keyVal.second;
  		if (second != null) {
  			value = second.toString() + " (" + second.getClass().getSimpleName() + ")";
  		}
  		holder.value.setText(value);
  
  		return convertView;
  	}
docs: Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML
  layout file. When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use {@link
  android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)} to specify a root view and to prevent attachment to the root.
  
  @param position
  The position of the item within the adapter's data set of the item whose view we want.
  @param convertView
  The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not
  possible to convert this view to display the correct data, this method can create a new view. Heterogeneous lists can specify their number of
  view types, so that this View is always of the right type (see {@link #getViewTypeCount()} and {@link #getItemViewType(int)}).
  @param parent
  The parent that this view will eventually be attached to
  
  @return A View corresponding to the data at the specified position.