Monday, September 21, 2015

Android Code Review- BaseAdapters are your Friend

Well, I am finally forcing myself to make the jump to iOS, but that is taking more time than I anticipated. More on that in the first iOS blog post. I did spend a little time doing some code review, bug fixing and refactoring. In that process I had a great conversation with one of the other Success Engineers at Xamarin, Colby Williams, who gave me some good feedback and reviewed some of my code. I learned one really great nuget that is worth sharing as it is not immediately apparent when getting started with Xamarin from Android.

When using collection views, it is almost always best to subclass BaseAdapter rather than use any of the out of the box adapters provided by Android (ArrayAdapter comes to mind). I was using the default ArrayAdapter for all of my drop down spinner controls and what I learned is most of the default Adapters provided by Android will give a potential performance hit because for each object in the list, an equal java object has to be created and maintained. This is due to how Xamarin and Android communicate with each other. For an in depth review, this document covers it well:

http://developer.xamarin.com/guides/android/under_the_hood/architecture

So what was happening was for every spinner I created using an Array Adapter, a general C# and Java object were being created and maintained, creating overhead. Instead, creating a BaseAdapter, the under the hood creates a single Java object that has a C# implementation within. Much better performance wise, fewer objects to maintain in memory.

My final code for the adapter is actually pretty simple:

public class SpinnerAdapter : BaseAdapter<string>
    {
        List<string> _items;
        Activity _context;
        public SpinnerAdapter (Activity context, List<string> items)
        {
            _items = items;
            _context = context;
        }

        public override long GetItemId (int position)
        {
            return position;
        }

        public int GetPosition(string selected)
        {
            return _items.IndexOf (selected);
        }

        public override string this[int index] {  
            get { return _items[index]; }
        }

        public override Android.Views.View GetView (int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
        {
            var view = convertView;
            if(view == null)
            {
                view = _context.LayoutInflater.Inflate (Resource.Layout.spinner_item, null);
            }

            view.FindViewById<TextView> (Resource.Id.text).Text = _items[position];

            return view;
        }

        public override int Count {
            get {
                return _items.Count;
            }
        }
    }


Once I made that update, I noticed my views loaded much quicker.

Next time I am going to dig into iOS development, and why it can be a challenge. Given that iOS 9 just came out this past week, I am also using this as an "excuse" to learn iOS 9.

1 comment: