Android Adventures - Events |
Written by Mike James | ||||
Thursday, 20 October 2016 | ||||
Page 2 of 3
Place the cursor on the line and type Alt-Enter to see the suggestions for how to fix it. Select Implement methods: and select the methods you want to implement from the dialog box that appears. In this case there is a single onClick method and Android Studio generates a method stub for you to fill in: Next edit MyOnClickListener to read:
Notice we have now created a class with a single method which is our event handler. In a real case you would write lots of code in the event handler. That is step one completed. Next we move to the Activity and place a Button on the design surface. At the end of the onCreate method we first retrieve the Button object:
remember to use Alt-Enter to add any import statements that are needed. Next we create an instance of our event listener:
and finally we use the button's setOnClickEventListener method to connect its onClick event to our new listener object:
That is putting it all together, minus some of the extra generated code:
Now if you run the program you will find that the onClick function in the MyOnClickListener instance is called when the button is clicked. BreakpointThe easiest way to check that the event handler is called is to place a breakpoint on the first line of the onClick method. To place a breakpoint simply click in the "margin" next to the line of code. A red blob appears:
Now when you run the program using the Debug icon or the Run,Debug command the program will stop when it reaches any line of code with a breakpoint set. Once the program pauses you can see where it has reached in its execution and you can examine what is stored in all of the variables in use. You can also restart the program or step though it. We will have more to say about debugging in a later chapter but for now it this small introduction is enough to save you a lot of time. Other EventsThe same overall method of creating a class that implements a method works for any type of event. You simply have to discover the name of the event listener interface, create a class that implements it, create an instance of the class and register the listener with the component that generates the event using a method something like setOnEvent(handler). Notice that you register the event object i.e. listener and not the event handler method i.e. not onClick(). This is a perfectly good method of implementing event handler but it isn't very practical because you are going to need to create a new class for every event you want to handle and in addition these classes are going to contain one method and be instantiated just once. That is a lot of boiler plate code for something that you are going to have to do often. There is also the problem of naming. You have to find a name for a class that is handling a click event from say a button and another that handles the same event from a textbox and so on. Then you also need a name for each instance you create and you end up with lots of names like button1OnClickClass and button1OnClickObject and ... There has to be a better way! Now that you have seen the fundamentals of Java event handling we can exporle the two ways that it tends to be done in practice. Two More Ways To Handle An EventTo avoid the overheads you can use one of two possible methods.
The first is something of "clever fix" and it relies on the fact that any class including your Activity can implement an interface. The second is based on the use of an anonymous class which is a language feature that was introduced to Java specifically to help with the need to create an instance of a class without having to actually create a class file or even give the class a name. Of the two the anonymous class is probably the best way to go about things but you will see both used in other peoples code and code examples so you need to know about both. It is worth saying at this early stage that there is a third way of implementing event handlers that was introduced in Java 8 - the lambda expression. You can make use of this in Android Studio 2 but at the time of writing it involves changing the compiler in use and losing the advantages of instant run. Implement the interface in the activityOne, almost cheats way, of doing things is to simply use the MainActivity class to implement the event listener interface. After all you can specify any class as an event handler as long as it implements the correct interface. It doesn't matter to the event mechanism that the class also implements lots of other methods that have nothing to do with events. This seems a little strange when you first see it but it is the closest approach to the way other languages do the job. For example, to handle the onClick event we need to add the "implements" for the interface to the Activity:
Now all that has to happen is that the Activity class has to implement the onClick event handler. Don't worry about the fact that the line has a read underlining indicating an error - the error is that you have to implement the method. To do this place the cursor in implements and use alt enter to display a menu of options that includes implement methods.
If you select this you can select the methods you want to implement and Android Studio will add them to your code. In this case we just want to implement onClick:
All that remains is to add the event listener using setOnClickEventListener but what is the instance of the class that is providing the event handler? If you recall what happens is that the system creates an instance of the MainActivity class to get your app running and the current instance of a class is always "this". So we need to add to the onCreate method:
In many ways this last way of doing things is the simplest. It has the disadvantage that you have to add an "implements" for each event you are going to handle but this could be an advantage in that it enables you to see what events are being used in your Activity. Also notice that using this method you set all of the event handlers using and instruction like
Which also implies that you will be using the same event handler for an event irrespective of which control generated the event. That is you will write a single onClick function and this will be used for all of the controls that you use setOnClickEvent(this) on. To handle this situation your event handler has to start by finding out which control generated the event and then deal with it appropriately. If you want to use multiple event handlers - one for each control then you need to use the anonymous class approach. |
||||
Last Updated ( Saturday, 22 October 2016 ) |