9.1 What is the service?
Service is a solution that runs in the background of Android, and it is ideal for performing tasks that do not require interaction with the user and require long-term operation. The operation of the service does not depend on any user interface, even if the program is switched to the background, or if the user opens another application, the service remains operational.
It is important to note, however, that the service is not run in a separate process, but rather relies on the application process in which the service was created. When an application process is killed, all services that depend on the process also stop running.
In addition, do not be confused by the background concept of the service, in fact, the service does not automatically open the thread, all the code is run by default in the main thread. In other words, we need to manually create sub-threads within the service and perform specific tasks here, otherwise the main thread is likely to be blocked. So in the first lesson of this chapter, let's take a look at the knowledge of Android multithreaded programming.
9.2 Android Multithreaded Programming
Familiar with the Java you, multithreaded programming must not be unfamiliar with it. When we need to perform some time-consuming operations, such as initiating a network request, taking into account the speed and other reasons, the server may not immediately respond to our request, if
Do not put such operations in the sub-thread to run, it will cause the main thread is blocked, thereby affecting the user's normal use of the software. So let's start with the basic usage of threading.
Basic usage of 9.2.1 threads
Android multithreaded programming is no more than Java multithreaded programming beads, basically all using the same syntax. For example, defining a thread only requires a new class to inherit from thread, then rewrite the parent class's run () method, and write the time-consuming logic in it, as follows:
class MyThread extends Thread {
@Override
public void Run () {
// handling of specific logic
}
}
So how do you start this thread? It is also very simple, just need to new out of the MyThread instance, and then call its start () method, so that the code in the Run () method will run in the child thread, as follows:
New MyThread (). Start ();
Of course, the use of inheritance is a bit high coupling, more time we will choose to implement the Runnable interface to define a thread, as follows:
Class MyThread implements Runnable {
@Override
public void Run () {
// handling of specific logic
}
}
If you use this notation, the method of starting the thread needs to change accordingly, as follows:
MyThread MyThread = new MyThread ();
New Thread (MyThread). Start ();
As you can see, the thread's constructor receives a Runnable parameter, and our new MyThread is the object that implements the Runnable interface, so it can be passed directly into the thread's constructor. The start () method of the thread is then called, and the code in the Run () method runs in the child thread. Of course, if you don't want to define a class specifically to implement the Runnable interface, you can also use anonymous classes, which is more common, as shown here:
New Thread (new Runnable () {
@Override
public void Run () {
// handling of specific logic
}
}). Start ();
The use of several of these threads is not familiar to you, because creating and starting threads in Java is the same way. After understanding the basic usage of threads, let's look at the different places where Android multithreaded programming differs from Java multithreaded programming.
9.2.2 updating the UI in a child thread
Like many other GUI libraries, Android's UI is also thread insecure. That is, if you want to update the UI elements in your application, you must do so in the main thread, or an exception will occur. Seeing is believing, let's go through a concrete example to verify it. Create a new Androidthreadtest project, and then modify the code in the Activity_main.xml as follows:
<relativelayout xmlns:android= " HT tp://schemas.android.com/apk/res/android "android:layout_width=" match_parent "android:layout_height=" match_parent ">
<button android:id= "@+id/change_text" android:layout_width= "match_parent" android:layout_height= "Wrap_content" android:text= "Change Text"/>
<textview android:id= "@+id/text" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" Android:layout_centerinparent= "true" android:text= "Hello World" android:textsize= "20sp"/>
</RelativeLayout>
Two controls are defined in the layout file, TextView is used to display a Hello world string in the center of the screen, the button is used to change what is displayed in the TextView, and we want to change the string displayed in the TextView to N when the button is clicked Ice to meet.
Next, modify the code in Mainactivity as follows:
public class Mainactivity extends Activity implements Onclicklistener {
private TextView text;
Private Button Changetext;
@Override
protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview ( R.layout.activity_main);
Text = (TextView) Findviewbyid (R.id.text);
Changetext = (Button) Findviewbyid (R.id.change_text);
Changetext.setonclicklistener (this);
}
@Override
public void OnClick (View v) {
Switch (V.getid ()) {
Case R.id.change_text:
New Thread (New Runnable () {
@Override
public void Run () {
Text.settext ("Nice to Meet You");
}
}). Start ();
Break
Default
Break
}
}
}
As you can see, we open a sub-thread in the Click event of the Change Text button and then call TextView's SetText () method in the child thread to convert the displayed string to Niceto meet you. The logic of the code is very simple, except that we are updating the UI in a child thread. Now run the program and click the Change Text button, and you will find that the program really crashes, as shown in 9.1.
Figure 9.1
Then look at the error log in LogCat, as shown in 9.2, as a result of updating the UI in a child thread.
Figure 9.2
This confirms that Android does not allow UI manipulation in child threads. But sometimes we have to do some time-consuming tasks in the sub-threads and then update the corresponding UI controls based on the results of the task.
For this scenario, Android provides a set of asynchronous message processing mechanisms that perfectly address the problem of UI manipulation in child threads. In this section, let's take a look at the use of asynchronous message processing, and then analyze its rationale in the next section.
Modify the code in the mainactivity as follows:
public class Mainactivity extends Activity implementsonclicklistener {
public static final int update_text = 1;
private TextView text;
Private Button Changetext;
Private Handler Handler = new Handler () {
public void Handlemessage (Message msg) {
Switch (msg.what) {
Case Update_text:
// You can perform UI operations here
Text.settext ("Nice to Meet You");
Break
Default
Break
}
}
};
......
@Override
public void OnClick (View v) {
Switch (V.getid ()) {
Case R.id.change_text:
New Thread (New Runnable () {
@Override
public void Run () {
Message message = new Message ();
Message.what = Update_text;
handler.sendmessage (message);// send message object out
}
}). Start ();
Break
Default
Break
}
}
}
Here we first define an integer constant Update_text, which is used to represent the update TextView action. Then add a Handler object and rewrite the parent class's Handlemessage method, where the specific message is processed. If you find that the value of the What field of Message is equal to Update_text, change the contents of the TextView display to Niceto meet you.
Here's another look at the code in the Click event of the Change Text button. As you can see, this time we did not directly perform UI operations on the thread, but instead created a Message (Android.os.Message) object and specified the value of its what field as Update_text, and then called Handler sendmess The age () method sends the message out. Soon, Handler receives this message and processes it in the Handlemessage () method. Note that the code in the Handlemessage () method is now running in the main thread, so we can safely do the UI here. Next, the value of the What field to carry with the Message is judged, and if it equals Update_text, the contents of the TextView display are changed to meet.
Now rerun the program and you can see Hello World in the center of the screen. Then click on the Changetext button to display the content is replaced with nice to meet you, 9.3 shown.
Figure 9.3
This way you have mastered the basic use of Android asynchronous message processing, and using this mechanism can be a great way to solve the problem of updating the UI in a child thread. But I'm afraid you're not quite sure how it works, so let's look at how the Android asynchronous message processing mechanism works.
9.2.3 parsing asynchronous message processing mechanism
Asynchronous message processing in Android consists of four parts, message, Handler, MessageQueue, and Looper. where Message and Handler have been touched in the previous section, and MessageQueue and Looper are new concepts for you, here's a brief introduction to these four sections.
1. Message
A message is an information that is passed between threads, and it can carry a small number of messages inside to exchange data between different threading. In the previous section we used the What field of the Message, in addition to using the Arg1 and Arg2 fields to carry some integral data, using the Obj field to carry an object.
2. Handler
Handler, as the name implies, is the meaning of the processor, which is primarily used to send and process messages. Sending a message is typically using the Handler sendMessage () method, and the emitted message is eventually passed to the Handler Handlemessage () method after a series of tossing and processing.
3. MessageQueue
MessageQueue is the meaning of Message Queuing, which is primarily used to store all messages sent through Handler. This part of the message will remain in the message queue and wait for it to be processed. There will only be one MessageQueue object in each thread.
4. Looper
Looper is the steward of MessageQueue in each thread, and after calling the Looper loop () method, it enters an infinite loop, and then whenever a message is found in MessageQueue, it is removed and passed to the Handler Han The Dlemessage () method. There will only be one Looper object in each thread. After understanding the basic concepts of Message, Handler, MessageQueue, and Looper, we'll come back to the asynchronous
The entire process of message processing is combed through. You first need to create a Handler object in the main thread and override the Handlemessage () method. Then, when UI action is required in a child thread, a message object is created and sent out through Handler. The message is then added to the MessageQueue queue for processing, and Looper tries to remove the pending message from MessageQueue and finally distributes it back to the Handlemessage () method of Handler. Since Handler is created in the main thread, the code in the Handlemessage () method will also run in the main thread, so we can do the UI operation safely here. The entire asynchronous message processing mechanism is shown in flow 9.4.
Figure 9.4
After a message has been called by such a process, it goes from a child thread to the main thread, from the inability to update the UI to the ability to update the UI, as is the core idea of the entire asynchronous message processing.
Android: The basics of Multithreaded programming