Event Handling

Last Android tutorial, explains the basic layouts in Android. This tutorial covers, the way to add event listeners to user interface components. After completing this tutorial, you must be able to find the user interface components at the runtime using findViewById method, read an input from an EditText, check the status of CheckBox and RadioButton, and handle the click events using OnClickListener.

Step 1:
Download the template from this link. To focus on event handling only, the XML design is already completed in this project.


GUI components have been created in the activity_main.xml, but the event handling code has to be written in pure Java. There is a million dollar question; how does Java identify the XML user interface components? All the XML GUI components have their relative Java classes in Android API. At the runtime, Android reads the XML layout and create the graphical user interface by creating Java objects for those GUI components defined in the XML. For example an EditText defined in the XML is treated as an android.widget.EditText object. In Android API all these components are sub classes of android.view.View class. There is one more problem... Android creates the Java objects at the runtime somewhere in memory. How can we access them from Java code(we need references to access those objects)? This is the place a mapping class R.java comes to stage. You can see the R.java in your package, if your project explorer is in Package perspective as shown below.
WARNING: YOU SHOULD NOT MODIFY THE R.JAVA



Open the R.java and search for activity_main.

public static final class layout {
    // some other constants
    public static final int abc_simple_dropdown_hint = 0x7f030016;
    public static final int activity_main = 0x7f030017;
    public static final int support_simple_spinner_dropdown_item = 0x7f030018;
}

The assigned value to the activity_main may be different for you. Name of this constant variable is exactly same as the file name of the activity_main.xml. Then search for btnOrder, which is the id of "Order" button in the layout.

public static final class id {
    // some constants here
    public static final int btnCancel = 0x7f080042;
    public static final int btnOrder = 0x7f080043;
    public static final int checkbox = 0x7f080029;
    public static final int chkCream = 0x7f08004b;
    public static final int chkSugar = 0x7f08004c;
    // some constants here
    public static final int txtChoices = 0x7f08004a;
    public static final int txtCoffeeType = 0x7f080046;
    public static final int txtNumber = 0x7f080044;
    public static final int txtTitle = 0x7f080040;
    // some constants here
}

Not only the btnOrder, all the ids defined in the activity_main.xml are there in R.java's inner class id. This id is used to identify the objects at the runtime. Go to the MainActivity.java class' onCreate method. There must be a statement setContentView(R.layout.activity_main), which binds the acitivity_main.xml with the MainActivity class.

There are instance variables defined in the MainActivity class as shown below. These variables are defined by me as the references to GUI components.
private EditText etNumber;
private RadioButton optDecaf;
private RadioButton optExpresso;
private RadioButton optColombian;
private CheckBox chkCream;
private CheckBox chkSugar;
private Button btnOrder;
private Button btnCancel;

Step 2:
Modify the findViews method as given below.
/**
 * Find the GUI components at the runtime.
 */
private void findViews() {
    this.etNumber = (EditText) findViewById(R.id.etNumber);
    this.optColombian = (RadioButton) findViewById(R.id.optColombian);
    this.optExpresso = (RadioButton) findViewById(R.id.optExpresso);
    this.optDecaf = (RadioButton) findViewById(R.id.optDecaf);
    this.chkCream = (CheckBox) findViewById(R.id.chkCream);
    this.chkSugar = (CheckBox) findViewById(R.id.chkSugar);
    this.btnCancel = (Button) findViewById(R.id.btnCancel);
    this.btnOrder = (Button) findViewById(R.id.btnOrder);
}

The findViewById(int) method needs the int id of desired GUI component as an argument and returns the object of that component as a View reference. A down-casting is required to cast the View reference to desired sub class reference. findViews method is called from the onCreate method. onCreate is an Android life cycle method which is called when the activity is created by Android. The super.onCreate() method creates the infrastructure of the Activity and setContentView method is used to bind the XML file to that activity. Remember that the GUI components are created, only after the super.onCreate() and setContentView are executed. Suppose if we called findViewById method before setContentView method, findViewById would return a  null reference.

Step 3:
Create and assign OnClickListener object to the btnOrder and btnCancel as shown below.

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

    // 1. Find the GUI components
    findViews();

    // 2. Set the on click listeners for buttons
    btnOrder.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onOrderClicked();
        }
    });

    btnCancel.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onCancelClicked();
        }
    });
}
Button has setOnClickListener method (inherited from android.view.View) with a parameter View.OnClickListener, so a View.OnClickListener object has to be passed to that method. In the given code an anonymous object is created within the method call. (To keep the code clean, the implementation is separated in another method onOrderClicked/onCancelClicked.)

Step 4:
Modify the onOrderClicked method as given below.
/**
 * The logic to execute when the btnOrder is clicked.
 */
private void onOrderClicked() {
    String coffee;
    String message;
    // EditText.getText() returns Editable not String
    String number = etNumber.getText().toString();
    // Check the CheckBoxes
    boolean cream = chkCream.isChecked();
    boolean sugar = chkSugar.isChecked();

    // Check the RadioButtons for selection
    if (optExpresso.isChecked()) {
        coffee = "Expresso";
    } else if (optColombian.isChecked()) {
        coffee = "Colombian";
    } else {
        coffee = "Decaf";
    }

    // Create a message
    if (cream && sugar) {
        message = coffee + " with cream and sugar.";
    } else if (cream) {
        message = coffee + " with cream.";
    } else if (sugar) {
        message = coffee + " with sugar.";
    } else {
        message = coffee + ".";
    }

    message = "Order no: " + number + ".\n" + message;

    // Show the message
    showMessage(message);
}
EditText has two frequently used methods getText and setText(Inherited method). As the name suggests getText returns the content of the EditText and the setText is used to display a text value. Notice that the getText method returns an Editable object not a String object, because String is an immutable object and any modification on that object causes to new garbage objects. Garbage objects cause executing garbage collector frequently and it reduces the performance of mobile device. Editable is a mutable object, so any modification can be done without introducing any garbage. CheckBox and RadioButton have isChecked method, which returns true or false based on their state.

Step 5:
Modify the  onCancelClicked method as given below. Activity.finish() method closes the current activity. This application has only one Activity, so it can be considered as closing the application.
/**
 * The logic to execute when the btnCancel is clicked.
 */
private void onCancelClicked() {
    this.finish();  // Close the application.
}

Step 6:
Save and run the application.


For the completed project click here.

Note
showMessage method uses Toast to display a pop up message. More about Toast will be covered in another tutorial. In this tutorial, we have started with a given template of code and completed the application by adding event handling code. To test your understanding, try to complete the given sample problem.

Sample Problem
A template of Android login activity project is given here. Download the template and develop the project from that template. The layout is already designed for you and you need to implement the logic only. If the username is "javahelps" and the password is "abc123" then the application should display a message "Welcome to dashboard". Otherwise, it should display a meaningful message based on the scenario. The logic behind the message is already implemented in the onLoginClicked method.


In the MainActivity.java, // TODO: comments are given in the places where you need to change the code. Complete the project by finding GUI components, setting OnClickListener and getting user inputs. Finally, run the project and check the output.

Find the projects at Git Hub.
Previous
Next Post »

Contact Form

Name

Email *

Message *