Programming with Java: Some Observations about Android's Classes - dummies

Programming with Java: Some Observations about Android’s Classes

By Barry A. Burd

When you start a new Java project, Android Studio offers to create an activity for your project. Android Studio offers you several different kinds of activities, such as a Basic Activity, an Empty Activity, a Login Activity, and so on. If you ask for an Empty Activity, you get this code:

package com.allyourcode.a10_11;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

 

public class MainActivity extends AppCompatActivity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

}

The code declares a class named MainActivity. This name MainActivity isn’t part of the Android API library. It’s a name that you make up when you create a new Android project. (Actually, Android Studio makes up the name. You accept the name or change it to some other name when you follow the steps to create a new project.)

The MainActivity class extends a class that belongs to Android’s SDK library, namely, the AppCompatActivity class. In other words, the MainActivity object is an AppCompatActivity object. The MainActivity object has all the rights and responsibilities that any AppCompatActivity instance has. For example, the MainActivity has an onCreate method, which it override.

In fact, the MainActivity class inherits about 460 lines of code from Android’s AppCompatActivity class, which inherits about 1,000 lines from Android’s FragmentActivity class, which inherits about 6,700 lines from Android’s Activity class. The inherited methods include ones such as getCallingActivity, getCallingPackage, getParent, getTitle, getTitleColor, getWindow, onBackPressed, onKeyDown, onKeyLongPress, onLowMemory, onMenuItemSelected, setTitle, setTitleColor, startActivity, finish, and many, many others. You inherit all this functionality with two simple words: extends AppCompatActivity.

In the terminology of familial relationships, your MainActivity class is a descendant of Android’s Activity class. Your MainActivity class is a kind of Activity.

This image, taken directly from Android’s online documentation, summarizes this information about the AppCompatActivity class.

java-programming-for-android-developers-2e-appcompatactivity
An AppCompatActivity family tree.

Bookmark the page for easy access to Android’s API library documentation.

In addition to being a subclass, the AppCompatActivity class implements a bunch of interfaces, including the AppCompatCallback interface, the TaskStackBuilder interface, and others. You don’t have to remember any of this. If you ever need to know it, you can look it up on Android’s documentation page.

Java’s super keyword, revisited

The word super stands for the superclass’s constructor. Different code used the super keyword in a different ways. Yes, super always has something to do with a class’s parent class. But, no, super doesn’t always refer to the parent class’s constructor.

In an onCreate method, the call super.onCreate(savedInstanceState) sends savedInstanceState to the parent class’s onCreate method. The parent class is the AppCompatActivity class. So Java calls the AppCompatActivity class’s onCreate method.

The AppCompatActivityclass’s onCreate method contains its own call to super.onCreate(savedInstanceState). The AppCompatActivity class’s parent is the FragmentActivity class. So Java passes savedInstanceState to the FragmentActivity class’s onCreate method. And so on.

It’s not until you get to the Activity class — your MainActivity class’s great-grandparent — that the code makes direct use of the savedInstanceState variable. From this savedInstanceState information, the code puts the activity back the way it was before the system destroyed it.

Casting, again

When you call findViewById, Java doesn’t know what kind of view it will find. The findViewById method always returns a View instance, but lots of Android’s classes extend the View class. For example, the classes Button, TextView, ImageView, CheckBox, Chronometer, and RatingBar all extend Android’s View class. If you type the following code:

// DON'T DO THIS!!

 

TextView textView;

 

textView = findViewById(R.id.textView);

Java lets out a resounding, resentful roar: “How dare you assume that the object returned by a call to findViewById refers to an instance of the TextView class!” (Actually, Java quietly and mechanically displays an Incompatible types error message in Android Studio’s editor.)

Narrowing means trying to assign a long value to an int value. A long value has 64 bits, and an int value has only 32 bits. So the attempt at narrowing fails. In the code you find here, the bad findViewById call is another attempt to do narrowing — assigning the View value returned by a method call to a TextView variable. The TextView class is a subclass of the View class, so the assignment fails miserably.

appease the Java gods by adding a casting operator to the code. You tell Java to convert whatever pops out of the findViewById method call into a TextView object.

textView = (TextView) findViewById(R.id.textView1);

While you’re typing the code, Java humors you and says, “Your casting operator shows me that you’re aware of the difference between a TextView and any old View. I’ll do my best to interpret the View object that I find at runtime as a TextView object.” (Actually, while you’re typing the code, Java says nothing. The fact that Java doesn’t display any error messages when you use this casting trick is a good sign. Java’s casting feature saves the day!)

Casting prevents you from seeing an error message while you develop your code. In that way, casting is quite a useful feature of Java. But casting can’t save you if your code contains runtime errors. When you type

textView = (TextView) findViewById(R.id.textView1);

you verify that the name textView represents a TextView widget. When the app runs, Java grabs the R.id.textView widget from the activity_main.xml file, and everything works just fine. But you may sometimes forget to check your R.java names against the components in the XML file. A call to findViewById surprisingly spits out a Button component when your casting tells Java to expect a TextView widget. When this happens, Java chokes on the casting operator and your app crashes during its run. Back to the drawing board!