In this collection of articles about Android, I will guide you through the basic topics that you'll need to get started in this mobile world - even if you're completely new to the Android operating system.
Android Basics
Let's start with a little history: What is Android?
According to Wikipedia,
"Android is a mobile operating system developed by Google, based on the Linux kernel and designed primarily for touchscreen mobile devices such as smartphones and tablets. Android's user interface is mainly based on direct manipulation, using touch gestures that loosely correspond to real-world actions, such as swiping, tapping and pinching, to manipulate on-screen objects, along with a virtual keyboard for text input."
As the most of you know, the Android system runs its features using applications.
So, let's take a deeper look.
Styles & Fragments
In this first article we will talk about activities, fragments, show example codes, and look at the lifecycle of the Android application.
- Activity is the part where the user will interacts with your application. In other words, it is responsible for creating a window to hold your UI components. (UI components and how to build a layout will be discussed in another article).
- Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and to which you can add or remove while the activity is running (sort of like a "sub activity" that you can reuse in different activities). And it must always be embedded in an activity. The fragment's lifecycle is directly affected by the host activity's lifecycle - in other words, a fragment cannot be instantiated alone!
Lifecycle
When an application is opened and shows its first activity, it follow a specific lifecycle. Within this, you can handle when the activity is destroyed, paused, resumed, or created.
The fragment lifecycle is embedded within the activity lifecycle but has some details and extra steps in it. The following image compares both lifecycles: on the left, the activity, and on the right, the fragment:
In the image we can see a lot of callbacks. Some we must implement, and others no. But what is the correct execution order, and which ones do we need to implement?
The only mandatory callback that we should override is onCreate for the activity and onCreateView for fragment, because we define the layout and do the mapping of the UI components inside of them.
When an activity is coming to the foreground and becoming visible to the user, it goes through the onCreate method that creates the activity layout, from the XML. After that it will go through the onStart and soon after the "onResume", in which the activity is already visible on the screen.
Now when we enter the background (we pressed home or another activity entered in front of it) it goes to the onStop method and when it comes back to the foreground it executes the onRestart methods and then the onStart and onResume normally, since it was only in the background and does not need to be re-created.
And finally when the activity is destroyed, for any reason (for example, pressing the back button) it follows the following flow: onStop and onDestroy in which all the resources of this activity are released and it exits the system activity stack. In this case, if we call this activity again, as it was destroyed, then it will start its flow from the onCreate because it needs to be re-created and added again in the stack.
So let's put together all this information:
- onCreate(activities) / onCreateView(fragments): The only required method (that is, it needs to be overwritten by the class that extends Activity) defines what the layout of that activity is (with the "setContentView" method) and where the XML components are mapped to the code.
- onStart: This method is always executed right after the onCreate and whenever the activity returns from background to foreground through onRestart.
- onResume: It always runs before the application appears to the user. At that moment this activity is already at the top of the activity stack and is visible to the user.
- onPause: Called when the system is about to start resuming another activity. This method is generally used to confirm unsaved data changes, stop animations among other things that may be consuming CPU, and so on.
- onRestart: Called when an activity that was stopped in the background is returning to the foreground because the activity that was visible above it is being destroyed or called. It always runs when an activity is in the STOP state.
- onStop: Called when the activity is no longer visible to the user. This can happen because it is being destroyed or is going to background so that another activity takes its place at the top of the stack and is visible to the user.
- onDestroy: Called before destroying the activity. This is the last call that activity will take when it is leaving the activity stack - that is, it is being destroyed - it is called because the activity is terminating (someone called finish ()), or because the system is temporarily destroying this activity instance to save space.
Now that we know about the theory, have a look at the code! Examples can be found by following the github link at the end of this article.
Layout
First let's take a look at the layout file. An Android layout is where the visual structure of your app or widget is set. In it are placed the components that will appear on the screen and perform the tools to interact with the user.
There are 2 ways to instantiate Android graphics components:
- First - and highly recommended - create the elements in an XML file.
- Second, instantiate the graphical elements at runtime, by the code of your application.
Declaring the whole layout part of your app in an XML file, we were able to separate the graphical interface from the source code, leaving the structure of the project more organized and easier to understand.
Following we have an simple layout of a login screen in the 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"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="50dip"
android:layout_marginTop="40dip"
android:gravity="center"
android:textSize="20sp"
android:textStyle="bold"
android:text="@string/app_name"/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:gravity="center"
android:textSize="16sp"
android:text="@string/username"/>
<EditText android:id="@+id/main_user_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dip"
android:layout_marginEnd="10dip"
android:inputType="text"
android:gravity="center"/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dip"
android:gravity="center"
android:textSize="16sp"
android:text="@string/password"/>
<EditText android:id="@+id/main_password_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dip"
android:layout_marginEnd="10dip"
android:inputType="textPassword"
android:gravity="center"/>
<Button
android:id="@+id/main_button_login"
android:layout_width="match_parent"
android:layout_height="40dip"
android:layout_margin="30dip"
android:text="@string/login"/>
</LinearLayout>
Binding the Layout
Now that we already did the XML for our screen, we need to tell the activity which layout to use and "bind" the components of the XML with the code, so we can get info and/or handle user interactions.
For this we will use the method setContentView inside the onCreate (in activity) or onCreateView (in fragment) to tell the code the layout of that screen.
In the following example we set the layout and after that we "bind" the element from the layout using the findViewById method that will search for a view in the XML with the respective id. We do a cast, (EditText), because the find view returns a parent view object.
public class MainActivity extends Activity {
private EditText mUserInput = null;
private EditText mPassInput = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUserInput = (EditText) findViewById(R.id.main_user_input);
mPassInput = (EditText) findViewById(R.id.main_password_input);
Button loginButton = (Button) findViewById(R.id.main_button_login);
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// do something when click
}
});
}
}
To do this in the fragment it's a little different but the concept is the same. Let's take a look at the example.
The onCreateView need to return the inflated view to its parent, so we use the layout inflater parameter to reference the view for the specific layout (in this case R.layout.activity_main).
After that we "bind" the components from the inflated view object and at the end we return it.
public class ExampleFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View inflatedView = inflater.inflate(R.layout.activity_main, container, false);
mUserInput = (EditText) inflatedView.findViewById(R.id.main_user_input);
mPassInput = (EditText) inflatedView.findViewById(R.id.main_password_input);
return inflatedView;
}
}
To Conclude
Today we covered the basics for creating a simple screen activity and binding the layout components with code in order to manipulate it.
In future articles we'll discuss other topics such as persistence, network and application flow.
Thanks for reading and feel free to reach out to me with any questions about it!
All the code is available at my github, feel free to use it: https://github.com/DeKoServidoni/android_study
Author
André Servidoni
André Servidoni is an Android Engineer at Avenue Code. He is a new technologies enthusiast, and he is addicted to PS4.