In Android adapters are used sometimes to provide objects for a spinner.
The following example shows how to extend that mechanism to add a null object. It was written using C# and Xamarin, but there should be no port to convert them to Java.
Object base class:
public class DatabaseObject { public DatabaseObject() { this.ID = -1; } public int ID { get; set; } }
Generic Adapter:
internal class GenericAdapter<T> : BaseAdapter<T> where T : DatabaseObject { protected Activity context = null; protected List<T> list = null; public GenericAdapter(Activity context, List<T> list) { this.context = context; this.list = list; } #region implemented abstract members of BaseAdapter public override long GetItemId(int position) { if (list == null) return long.MinValue; return list[position].ID; } public override View GetView(int position, View convertView, ViewGroup parent) { View view = convertView; // re-use an existing view, if one is available if (view == null) // otherwise create a new one view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null); view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = list[position].ToString(); // <= Make sure .ToString() returns something! return view; } public override int Count { get { if (list == null) return 0; return list.Count; } } public override T this[int index] { get { if (list == null) return null; return list[index]; } } #endregion }
Model Object Example:
public class Employee : DatabaseObject { public Employee() { } public string FirstName { get; set; } public string LastName { get; set; } public string Name { get { string s = LastName; if (!string.IsNullOrWhiteSpace(FirstName)) s += ", " + FirstName; return s; } } public override string ToString() { return Name; } }
Nullable Generic Adapter:
internal class GenericNullableAdapter<T> : GenericAdapter<T> where T : DatabaseObject { public GenericNullableAdapter(Activity context, List<T> list) : base(context, list) { } #region implemented abstract members of BaseAdapter public override long GetItemId(int position) { if (list == null || position == 0) return long.MinValue; return list[position - 1].ID; } public override View GetView(int position, View convertView, ViewGroup parent) { View view = convertView; // re-use an existing view, if one is available if (view == null) // otherwise create a new one view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null); if (position == 0) view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = "(" + context.GetString(Resource.String.Empty) + ")"; else view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = list[position - 1].ToString(); return view; } public override int Count { get { if (list == null) return 0; return list.Count + 1; } } public override T this[int index] { get { if (list == null || index <= 0) return null; return list[index - 1]; } } #endregion }
Using in spinner:
// Setting values var spinner = FindViewById<Spinner>(Resource.Id.SpinnerEmployee); var adapter = new GenericNullableAdapter<Employee>(this, employees); spinner.Adapter = adapter; if (item.Employee == null) spinner.SetSelection(0); else spinner.SetSelection(employees.IndexOf(item.Employee) + 1); // Getting values var spinner = FindViewById<Spinner>(Resource.Id.SpinnerEmployee); item.Employee = (spinner.Adapter as GenericNullableAdapter<Employee>)[spinner.SelectedItemPosition];