Building a Mobile Employee Directory – Step 2: Load data into the ListActivity from an XML file via XmlParser

| February 26, 2013 | 1 Comment

Parsing XML data with XmlPullParser into an Android ListView.

After reviewing the SAX (Simple API for XML) Parser, the DOM (Document Object Model) Parser and the XmlPullParser.  I’ve decided to use the XmlPullParser because it is supposed to be the fastest.  I have not tried the JDOM Parser.

employee_list.xml  (in res/xml)

<?xml version="1.0" encoding="utf-8"?>
<employees>
    <employee>
        <id>1</id>
        <firstName>John</firstName>
        <lastName>Doe</lastName>
        <title>CEO</title>
        <city>San Francisco, CA</city>
        <managerId>0</managerId>
        <department>Corporate</department>
        <officePhone>123-456-0001</officePhone>
        <mobilePhone>987-654-1234</mobilePhone>
        <email>John@mail.com</email>
        <picture>placeholder.jpg</picture>
    </employee>
    <employee>
        <id>2</id>
        <firstName>Barack</firstName>
        <lastName>Obama</lastName>
        <title>President</title>
        <city>Washington DC</city>
        <department>Corporate</department>
        <managerId>0</managerId>
        <officePhone>123-456-0002</officePhone>
        <mobilePhone>781-000-0002</mobilePhone>
        <email>Barack@mail.com</email>
        <picture>barack_obama.jpg</picture>
    </employee>
    <employee>
        <id>3</id>
        <firstName>Joe</firstName>
        <lastName>Biden</lastName>
        <title>VP</title>
        <city>Washington DC</city>
        <managerId>2</managerId>
        <department>Corporate</department>
        <officePhone>123-456-0003</officePhone>
        <mobilePhone>987-654-1234</mobilePhone>
        <email>Joe@mail.com</email>
        <picture>joe_biden.jpg</picture>
    </employee>
    <employee>
        <id>4</id>
        <firstName>Hillary</firstName>
        <lastName>Clinton</lastName>
        <title>Secretary of State</title>
        <city>Washington DC</city>
        <managerId>2</managerId>
        <department>Corporate</department>
        <officePhone>123-456-0004</officePhone>
        <mobilePhone>987-654-1234</mobilePhone>
        <email>Hillary@mail.com</email>
        <picture>hillary_clinton.jpg</picture>
    </employee>
</employees>

EmployeeXmlParser.java

package com.himebaugh.employeedirectory;

import java.io.IOException;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.Context;

public class EmployeeXmlParser {

	// names of the XML tags
	static final String EMPLOYEES = "employees";
	static final String EMPLOYEE = "employee";
	static final String ID = "id";
	static final String FIRSTNAME = "firstName";
	static final String LASTNAME = "lastName";
	static final String TITLE = "title";
	static final String DEPARTMENT = "department";
	static final String CITY = "city";
	static final String OFFICEPHONE = "officePhone";
	static final String MOBILEPHONE = "mobilePhone";
	static final String EMAIL = "email";
	static final String PICTURE = "picture";

	ArrayList<Employee> employeeList = null;
	private Employee currentEmployee = null;
	private boolean done = false;
	private String currentTag = null;

	public ArrayList<Employee> parse(Context context) {

		XmlPullParser parser = context.getResources().getXml(R.xml.employee_list);

		try {

			int eventType = parser.getEventType();

			// Following logic modified from http://www.ibm.com/developerworks/library/x-android/
			// Also look at http://developer.android.com/training/basics/network-ops/xml.html

			while (eventType != XmlPullParser.END_DOCUMENT && !done) {

				switch (eventType) {
				case XmlPullParser.START_DOCUMENT:
					employeeList = new ArrayList<Employee>();
					break;
				case XmlPullParser.START_TAG:
					currentTag = parser.getName();
					if (currentTag.equalsIgnoreCase(EMPLOYEE)) {
						currentEmployee = new Employee();
					} else if (currentEmployee != null) {
						if (currentTag.equalsIgnoreCase(ID)) {
							currentEmployee.setId(Integer.parseInt(parser.nextText())); 	
							// currentEmployee.setId(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(FIRSTNAME)) {
							currentEmployee.setFirstName(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(LASTNAME)) {
							currentEmployee.setLastName(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(TITLE)) {
							currentEmployee.setTitle(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(DEPARTMENT)) {
							currentEmployee.setDepartment(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(CITY)) {
							currentEmployee.setCity(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(OFFICEPHONE)) {
							currentEmployee.setOfficePhone(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(MOBILEPHONE)) {
							currentEmployee.setMobilePhone(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(EMAIL)) {
							currentEmployee.setEmail(parser.nextText());
						} else if (currentTag.equalsIgnoreCase(PICTURE)) {
							currentEmployee.setPicture(parser.nextText());
						}
					}
					break;
				case XmlPullParser.END_TAG:
					currentTag = parser.getName();
					if (currentTag.equalsIgnoreCase(EMPLOYEE) && currentEmployee != null) {
						employeeList.add(currentEmployee);
					} else if (currentTag.equalsIgnoreCase(EMPLOYEES)) {
						done = true;
					}
					break;
				}
				eventType = parser.next();
			}

		} catch (XmlPullParserException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return employeeList;

	}

}

MainActivity.java

package com.himebaugh.employeedirectory;

import java.util.List;

import android.app.ListActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ArrayAdapter;

//	GOAL: Build a native android Mobile Employee Directory 

//	** The result is similar to the sample with Flex and Flash Builder 
//	see http://www.adobe.com/devnet/flex/articles/employee-directory-android-flex.html

//	PURPOSE: Learning how to build an Android App.

//	Step 2: Load data into the ListActivity from an XML file via XmlParser
//			1) employee_list.xml  (in res/xml)
//			2) Employee.java
//			3) EmployeeXmlParser.java

public class MainActivity extends ListActivity {

	public List<Employee> employees = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

        /*
         * This will work, but best practice is to place in a non-ui thread like below.
         *
         * EmployeeXmlParser parser = new EmployeeXmlParser();
         * employees = parser.parse(this);
         *
         * ArrayAdapter<Employee> adapter = new ArrayAdapter<Employee>(this, android.R.layout.simple_list_item_1, employees);
         * setListAdapter(adapter);
         */

        // Parse xml data in a non-ui thread
        new LoadEmployeesTask().execute();
	}

    private class LoadEmployeesTask extends AsyncTask<String, Void, List<Employee>> {

        @Override
        protected List<Employee> doInBackground(String... args) {

            // CALL XMLPULLPARSER & RETURN A LIST
            EmployeeXmlParser parser = new EmployeeXmlParser();
            employees = parser.parse(getBaseContext());

            return employees;
        }

        @Override
        protected void onPostExecute(List<Employee> employees) {

            ArrayAdapter<Employee> adapter = new ArrayAdapter<Employee>(getBaseContext(), android.R.layout.simple_list_item_1, employees);

            setListAdapter(adapter);

        }

    }

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

Employee.java

package com.himebaugh.employeedirectory;

public class Employee {
	Integer _empID;
	String _firstName;
	String _lastName;
	String _title;
	String _department;
	String _city;
	String _officePhone;
	String _mobilePhone;
	String _email;
	String _picture;

	// constructor
	public Employee() {

	}

	// constructor with parameters
	public Employee(Integer empID, String firstName, String lastName, String title, String department, String city, String officePhone, String mobilePhone, String email, String picture) {
		this._empID = empID;
		this._firstName = firstName;
		this._lastName = lastName;
		this._title = title;
		this._department = department;
		this._city = city;
		this._officePhone = officePhone;
		this._mobilePhone = mobilePhone;
		this._email = email;
		this._picture = picture;
	}

	// All set methods

	public void setId(Integer empID) {
		this._empID = empID;
	}

	public void setFirstName(String firstName) {
		this._firstName = firstName;
	}

	public void setLastName(String lastName) {
		this._lastName = lastName;
	}

	public void setTitle(String title) {
		this._title = title;
	}

	public void setDepartment(String department) {
		this._department = department;
	}

	public void setCity(String city) {
		this._city = city;
	}

	public void setOfficePhone(String officePhone) {
		this._officePhone = officePhone;
	}

	public void setMobilePhone(String mobilePhone) {
		this._mobilePhone = mobilePhone;
	}

	public void setEmail(String email) {
		this._email = email;
	}

	public void setPicture(String picture) {
		this._picture = picture;
	}

	// All get methods

	public Integer getId() {
		return this._empID;
	}

	public String getFirstName() {
		return this._firstName;
	}

	public String getLastName() {
		return this._lastName;
	}

	public String getTitle() {
		return this._title;
	}

	public String getDepartment() {
		return this._department;
	}

	public String getCity() {
		return this._city;
	}

	public String getOfficePhone() {
		return this._officePhone;
	}

	public String getMobilePhone() {
		return this._mobilePhone;
	}

	public String getPicture() {
		return this._picture;
	}

	//
	@Override
	public String toString() {
		return _firstName + " " + _lastName + "\n" + _title;
	}

}

activity_main.xml  (in res/layout)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >
    </ListView>

</RelativeLayout>

 

Screenshot of the application

App-EmployeeDirectory-01

 

Tags: , , ,

Category: Android Application Development

Comments (1)

Trackback URL | Comments RSS Feed

  1. Langdon Himebaugh says:

    The code has been place on GitHub. Download at https://github.com/langhimebaugh/EmployeeDirectory-Step-02

Leave a Reply to Langdon Himebaugh Cancel reply

Your email address will not be published. Required fields are marked *