Monday, October 21, 2013

Populating A ListView Using SQLite: Android

This is the first in a series of projects that form the components of a larger Android application project. We'll start slow with the basics so even those with little or no Android development experience and a basic working knowledge of Java can follow along quite easily.

That's the hope, anyway...

  • Creating a list using ListView
There are several kinds of Views in Android, and ListView is one of them. Go ahead and open up a new Android project in Eclipse/ADT and call it TheList. Name the main activity ListFiller (I'm leaving the XML layout file as activity_list_filler.xml).

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:id="@+id/theList"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>


If your layout file activity_list_filler.xml looks like what's in the text box and the Graphical Layout looks like the image below it, so far so good.

So, you're probably wondering what we're going to populate the list with (what goes in for each row item). Well, let's populate it with Objects that represent movies in a famous Sci-Fi movie series. We'll create a class called SWMovie.

SWMovie.java

package com.stirfriedcode.thelist;

public class SWMovie {
                   private long id;
                   private String movie;
                   private String episode;
                  
                   public SWMovie(String movie, String episode) {
                                     this.movie = movie;
                                     this.episode = episode;
                   }
                  
                   public long getId() {
                                     return id;
                   }
                  
                   public void setId(long id) {
                                     this.id = id;
                   }
                  
                   public String getMovie() {
                                     return movie;
                   }
                  
                   public void setMovie(String movie) {
                                     this.movie = movie;
                   }
                  
                   public String getEpisode() {
                                     return episode;
                   }
                  
                   public void setEpisode(String episode) {
                                     this.episode = episode;
                   }
}

As you can see, we've just created the class SWMovie with an object constructor and the usual getter/setter methods. The variable "id" will be used for the SQLite database we'll create after we're able to display our list appropriately.

Before we go any further, let's customize the rows in the list. In other words, let's decide the row layout. I figure we can divide each row in half with a top section containing the movie and the bottom section containing the episode. The first row in the list would look like this...


movie 1
episode 4

We create the row layout by creating an XML file called row_layout.xml.

row_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:gravity="center" >
   
    <TextView
        android:id="@+id/movie"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="15sp"/>
   
    <TextView
        android:id="@+id/episode"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="25sp"/>
   

</LinearLayout>

Let's take a look at our main activity page (ListFiller.java) and see where we're at...

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ListView;

public class ListFiller extends Activity {
             ListView movieList;

            @Override
             protected void onCreate(Bundle savedInstanceState) {
                           super.onCreate(savedInstanceState);
                           setContentView(R.layout.activity_list_filler);
                                    
                           movieList = (ListView) findViewById(R.id.theList);
                           movieList.setAdapter(//We need to make a custom adapter);
           }
We've declared our ListView and given it a name (movieList). We've also included code to create the list in the onCreate method. However, instead of using the generic ListAdapter I prefer to make a custom adapter, so let's do that now. Call the custom adapter MovieListAdapter and have it extend ArrayAdapter. When you create the new adapter class, it'll come up as 

public class MovieListAdapter extends ArrayAdapter<T>

T represents the kind of list object, so just replace it with SWMovie. The entire class should look like

MovieListAdapter.java
public class MovieListAdapter extends ArrayAdapter<SWMovie> {
         private int  resource;
         private LayoutInflater inflater;
         private Context context;
                  
         // our constructor takes 3 parameters; keep this in mind when you set the adapter.
         //  resourceId will be our row_layout resource. Context and List should be clear.
         public MovieListAdapter(Context ctx, int resourceId, List<SWMovie> objects) {
                 super( ctx, resourceId, objects );
                 resource = resourceId;
                 inflater = LayoutInflater.from( ctx );
                 context = ctx;
         }
                  
         @Override
          public View getView ( int position, View convertView, ViewGroup parent ) {
                                    
                  /* create a new view of my layout and inflate it in the row */
                  convertView = ( LinearLayout ) inflater.inflate( resource, null );

                  /* Extract the SWMovie object to show. getItem() comes from ArrayAdapter class */
                  SWMovie swMovie = getItem(position);
                                    
                  /* set SWMovie movie in movie TextView. getMovie is from our SWMovie class */
                  TextView txtMovie = (TextView) convertView.findViewById(R.id.movie);
                  txtMovie.setText(swMovie.getMovie());
                                    
                 /* set SWMovie episode in episode TextView */
                 TextView txtEpisode = (TextView) convertView.findViewById(R.id.episode);
                 txtEpisode.setText(swMovie.getEpisode());
                                    
                 return convertView;
         }
}


Now, back to the main activity. All the way through until the end of onCreate it looks like...

ListFiller.java
import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ListView;

public class ListFiller extends Activity {
ListView movieList;

        @Override
         protected void onCreate(Bundle savedInstanceState) {
                       super.onCreate(savedInstanceState);
                       setContentView(R.layout.activity_list_filler);
                                    
                       List myList = new ArrayList();
                       for (int i = 1; i < 4; i++) {
                           String g = Integer.toString(i);
                           int k = i + 3;
                           String j = Integer.toString(k);
                           myList.add(new SWMovie("Movie " + g, "Episode " + k));
                       }
                       for (int i = 1; i < 4; i++) {
                           String g = Integer.toString(i);
                           int k = i + 3;
                           String j = Integer.toString(k);
                           myList.add(new SWMovie("Movie " + k, "Episode " + g));
                       }
                                    
                       movieList = (ListView) findViewById(R.id.theList);
                       movieList.setAdapter(new MovieListAdapter(this, R.layout.row_layout, myList));
        }

                  
And, if we run our application (called TheList, remember?), we see...



So, we've created a ListView with customized rows, and we're no longer uncertain about which episodes were released before others...

Next time, we'll integrate the SQLiteDatabase class into our application code in order to save our data upon exiting the application.

(To Be Continued...)

Update: Go to Part 2 of this exercise

No comments:

Post a Comment