Android Deep Dive: Part 1 — Doing more with ArrayAdapters

Perry Eising
7 min readMay 24, 2017

Welcome to the first Android Deep Dive to be featured on my medium blog! If you don’t know me yet — I am a teacher at Epicodus, a code school located in Portland and Seattle in the Pacific NW. I teach the Mobile Development Track with Java/Android. Welcome! These Deep Dives will give you the opportunity to explore a new, in-depth topic, in a hands-on way, and get more of an idea of how the Epicodus curriculum is structured.

To get the most out of this Deep Dive, you should have some experience working with Android projects. Understanding how to create a new project, a new activity, and the basic structure of a class is essential. Also, you should have a basic understanding of what an Adapter is and how it works, specifically an ArrayAdapter.

If you are not quite ready yet to tackle this Deep Dive, we recommend you familiarize yourself first, either through our curriculum, or through another resource.

If you are ready to get started — great!

Review

If you recall from using an ArrayAdapter in the past, an Adapter allows us to bind a single instance of an Object to a layout that is held in a collection. If we have an Array of Strings, otherwise known as a String[], an ArrayAdapter pulls out a single String, and displays it in a layout. This process is then repeated until each String in the Array is displayed. Here is an example of how an ArrayAdapter might be implemented.

Even though we can customize our ArrayAdapter, and change the way data is displayed, for example through String.format(), we would still use a standard resource that is part of the Android package, namely simple_list_item_1 to display our data. Great! However, the standard ArrayAdapterreally can’t do very much — it can pull items, usually of type String out of an array, and draw a line underneath each one, but that’s about it.

But what if we want to change the way our list looks, or how the data is displayed? How do we achieve this? We need to create, at minimum, a custom adapter that extends the functionality of the ArrayAdapter. This is what we will be working through for this Deep Dive. Let’s set up our project and get some basics covered first.

Setting up our Project

Create a new project with all of the standard settings, as well as an empty activity called MainActivity.java:

Copy in the following code:

Before we move on, import all the necessary classes, and make sure you read through this code and get a rough idea of what we are trying to do here: We have some member variables that we are connecting to views from our layout (which we have not created), and we are also pulling in some information from our frontend and then what? We are moving to a new activity. So far so good. Let’s make the layout file next that is the other half of our activity — that’ll fix the red squiggly lines in our MainActivity.java.

In your activity_main.xml, copy in:

Now, we just need to create a second empty activity, namely RestaurantsActivity, that MainActivity is referring to in its onCreate(). Go ahead and create that activity now through new > empty activity.

Copy in the following code for your RestaurantsActivity.java:

Use the following code for activity_restaurants.xml:

Now, lets return to our RestaurantsActivity and invoke our ArrayAdapter correctly. On your onCreate(), add:

ArrayAdapter arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, restaurants);mListView.setAdapter(arrayAdapter);

Here, you are creating a new standard ArrayAdapter and providing it with the ArrayList of restaurants created earlier in your code.

Now, if you run your app, you should be able to enter a zipcode and see the following:

Great! We have a scrollable list of restaurants taken from our ArrayList. Obviously, these are always the same ones, regardless of zip, but this is a good start.

Now we can customize our ArrayAdapter to make our display a little bit more interesting.

Create the custom adapter

First, create a new Java class in the main package called MyRestaurantsArrayAdapter.

Our custom MyRestaurantsArrayAdapter class will need to extend the ArrayAdapter class.

public class MyRestaurantsAdapter extends ArrayAdapter {}

We are already showing the name of the restaurant in our ListView. Let’s add some more information, such as a cuisine type. We’ll store this information in a parallel array to keep things simple. (We could use a HashMap, but we’ll stick with Arrays for now.) We’ll need to pass these two bits of information (restaurants and cuisines) to our constructor, so we can use them when we output the data back to the UI. But we also need to pass in the Context, and a resource. Make sure the cuisines and the restaurants can be reached via the same index (i.e they match up)

private String[] restaurants = new String[] {“Sweet Hereafter”, “Cricket”, “Hawthorne Fish House”, “Viking Soul Food”, “Red Square”, “Horse Brass”, “Dick’s Kitchen”, “Taco Bell”, “Me Kha Noodle Bar”, “La Bonita Taqueria”, “Smokehouse Tavern”, “Pambiche”, “Kay’s Bar”, “Gnarly Grey”, “Slappy Cakes”, “Mi Mero Mole” };private String[] cuisines = new String[] {“Vegan Food”, “Breakfast”, “Fishs Dishs”, “Scandinavian”, “Coffee”, “English Food”, “Burgers”, “Fast Food”, “Noodle Soups”, “Mexican”, “BBQ”, “Cuban”, “Bar Food”, “Sports Bar”, “Breakfast”, “Mexican” };

Our constructor for our adapter now looks like this:

Context in Android is a term that comes up a lot, and is frequently required for many methods to run, such as Toasts. Context, simply put, is the current state of the application or object. We need it to get information regarding our app, or other parts of our app. Depending on where you are located in your app, such as an activity class, you can access Context via different methods such as getApplicationContext(), getBaseContext(), getContext(), or simply falling back on this.

Context is just another Object in Android, so don’t let it scare you! You can also pass Context around like any other variable, including into a constructor, like we are doing here.

The resource here refers to the XML file we are using in order to display our data. We are not changing this at this time. Remember, adapters need three pieces of information, minimum:

* Information about where they are being invoked (Context),

* Information about which layout file they are utilizing (resource, in this case simple_list_item_1)

* Some form of data storage (an Array or ArrayList of String’s or Objects, most likely).

So far so good. Our custom adapter is taking shape.

Because MyRestaurantsArrayAdapter inherits from ArrayAdapter, we need to Override some of ArrayAdapter’s methods and replace them with our own custom versions. This is where we can format out output string! Getting closer.

OK, so let’s take a look at this weird line:

String formattedString = String.format(“%s \nServes great: %s”, restaurant, cuisine);

is what every list item will look like. We could concatenate with +here, but this is a good opportunity to practice String interpolation. The %s represent each value after the closing “, separated by commas. The \n is how we can create a new line in Java, to make our formatting even nicer. String interpolation is a little more sophisticated than concatenating, so make sure you use it!

What else?

Calling super() from a subclass allows you to reference a method that was overridden. It also allows you to call both the original and the overridden method from a subclass, or call the method from the superclass from within the overriding method from the subclass. If you remove this line, you’ll see that Android Studio will get unhappy. But why? We need this here as we are inheriting from a class that doesn’t provide a default, parameterless constructor. In these cases, you’ll need to explicitly call super() from the constructor of your subclass, passing in parameters the base constructor needs.

We don’t need to worry about where the int position is coming from, ArrayAdapter takes care of that under the hood.

Similarly, as mentioned in the comment, we do not explicitly call getCount(), but we need this to be here nonetheless. ListView requires it, so it knows how many items to draw into the UI.

Alright, we are nearly done with our adapter — now we just need to change how our adapter is called.

Jump back over to RestaurantsActivity.java.

Here, we need to change how from invoking boring ArrayAdapter to invoking our cool custom MyRestaurantsArrayAdapter as follows:

MyRestaurantsArrayAdapter adapter = new MyRestaurantsArrayAdapter(this, android.R.layout.simple_list_item_1, restaurants, cuisines); //must match constructor!

Take it for a spin, you should see something that looks like this:

Great work! You have successfully learned to create and implement your own flavour of ArrayAdapters! Well done.

--

--

Perry Eising

Tech | Advocacy | Diversity | Queer | Adventure. Whiskey - rocks - no chaser.