Android tasks, processes, and threads

Source: Internet
Author: User
Tasks, processes, and threads
The components and Applications in Android are mostly static. When an application runs, it will inevitably need to care about the concept of processes and threads. In Android, the most distinctive concept in the Dynamic Running of components is the translation of tasks into tasks.
The main function of task intervention is to strip the connection between components from the details of the process concept. You can configure the components in a different model. In many cases, it simplifies the understanding of upper-level developers and helps them better develop and configure.

Task
In the SDK, there is a good example of a task (Guide/topics/fundamentals.html # acttask), that is, a task is equivalent to an application. In the eyes of developers, developing an android Program is an independent component, but for general users, what they perceive is only a running overall application, behind this whole is the task.
Task, in short, is a set of activity components that are aggregated in stack mode. They have potential pre-and post-drive associations. Newly Added activity components are located at the top of the stack. Only the activity at the top of the stack can have the opportunity to interact with users. When the activity at the top of the stack exits its mission, the task will unstack it and let the next activity at the top of the stack face to face, until no more activity exists in the stack, the task ends.

Event Task Stack

Open the email application and enter activity.
Select an email and click Activity B AB.
Click "reply" to start writing a new email (Activity C) ABC.
After writing a few lines of words, click Select contact to go to the select Contact Interface (Activity D) ABCD
Select the contact and continue to write the email ABC.
Write the email, send the email, and return to the original email AB.
Click Back to return to inbox
Exit email program null

As shown in the table above, it is an instance. The task stack changes from the user's entry into the mailbox to the completion of the reply and exit the application. This is a standard stack mode. For most situations, such a task model is sufficient. However, it will become much more cruel to involve actual performance and overhead. For example, starting a browser is a heavy process in Android. It requires a lot of initialization work and has a large memory overhead. But at the same time, opening some content with a browser is a common requirement for applications. Imagine how cruel it would be to start a browser if there are ten running applications (multiple tasks) at the same time, the ten task stacks are stacked with similar browser activities, which is a waste of splendor. Therefore, you may have the idea that a browser activity may exist as a separate task. The browser tasks will not be merged, regardless of the request from that task. In this way, although the browser activity itself needs to maintain more states, but the overall overhead will be greatly reduced, this kind of behavior for everyone is worthy of praise.
Android certainly supports such a commendable behavior. In Android, the task mode of each activity can be provided by the activity provider (through the configuration file ...) and the activity user (using the Flag Information in intent ...) configure and select. Of course, the user's control over the activity is limited to the scope permitted by the provider. The provider explicitly prohibits the mode, and the user cannot cross-border use.
In the SDK (Guide/topics/fundamentals.html # acttask), you can configure the two in the task mode, which is clearly written, I will explain it again (the complete configuration items must be checked by the SDK. Below are just a few of the frequently used items ...). The provider configures components through the configuration file (manifest) <activity>, while the caller makes a choice through the flag of the intent object. Compared with the standard task stack mode, the configuration has two main directions: one is to destroy the inbound and outbound rules or styles of the existing stack; the other is to open up a new task stack to complete the tasks that should have been completed in the same task stack.
For application developers, the launchmode attribute in <activity> must be dealt with frequently. It has four modes: "standard", "singletop", "singletask", and "singleinstance ".
Standard mode, which is the default and standard task mode. If this mode is used without other factors, an activity instance is constructed, when added to the caller's task stack, the standard mode is undoubtedly the most suitable for activities with average usage frequency and overhead, because the logic is simple and clear, so it is the default choice.
The singletop mode is basically the same as the standard mode. It is different only when the requested activity is located at the top of the stack. In this case, the activity configured as singletop will no longer construct a new instance and add it to the task stack. Instead, it will send the new intent to the top activity of the stack, the activity at the top of the stack can handle the new intent by reloading onnewintent (of course, you can ignore it ...). This mode reduces the repetitive overhead at the top of the stack and avoids some strange behaviors. (imagine, if several of them are the same activity at the top of the stack and exit at the same level, what is the user experience ...), it is suitable for displaying updated list activities. A living example is that in applications provided by Android by default, browser bookmarks (browserbookmarkpage) Use singletop.
The singletop mode breaks down the logic of the original stack (reusing the stack top without creating new elements into the stack...), but does not open up exclusive tasks. However, singletask and singleinstance both adopt a different path of task. Activity marked as singletask. Only one instance exists at most and is located in the task with it as the root. All requests to the activity will jump to the task of the activity to expand. Singletask, like the single-piece mode in concept, all modifications are based on an instance, which is usually used in activity with a high construction cost but a low switching cost. This mode is widely used in applications provided by the android source code. The most typical example is the main activity (called browser...) of the browser application ...), it is a window that displays the current tab and the content of the current page. It has a high construction cost, but the page switching is still fast. It works well with singletask.
In contrast, singleinstance is more extreme. In most cases, singleinstance and singletask are identical. The only difference is that the singleinstance Activity is the only activity in its stack. If other activities are involved, all are handed over to other tasks. This makes singleinstance activity, like an isolated island, a thorough black box. It does not care where the request comes from or who will execute it later. In Android's default applications, there are very few such activities. In my personal engineering practice, I tried to use them in the quick word activity of youdao dictionary, it is because I think it is convenient to get the word quickly (click to enter from notification) and it will be used in various occasions and should be completely independent.
In addition to the launchmode that can be used to allocate tasks, another attribute of <activity> taskaffinity is often used. Taskaffinity is a collection of things. It tends to throw activity with the same attributes of taskaffinity into the same task. However, its binding force is much weaker than launchmode. It takes effect only when allowtaskreparen ting in <activity> is set to true, or when the caller adds the flag_activity_new_task attribute of intent flag. If you have the opportunity to use the android notification mechanism, you can know that every activity triggered by notification must be called by an intent set to flag_activity_new_task. At this time, developers may need to properly configure the taskaffinity attribute so that the called activity can locate the organization and run in the task of the same taskaffinity.

Process
In the development of most other platforms, each developer has a very clear understanding of the process model of their own applications. For example, for a console program, you can imagine that it starts a process from the main function, ends with the main function, and the process is completed and exited; In the UI program, there is usually a message loop running. When the Exit message is received, the process of exiting the message loop ends. In the process of running the program, what processes are started, and communicate with third-party processes, etc. Every developer is clear in mind. The process boundary, here, is like a national border. Every crossing will leave a deep impression.
In Android programs, developers can directly perceive tasks. What is clear is the component boundary, and the process boundary is hard to figure out, even with process hosting. Android does not only deprive users of the power to manually forge memory, but does not hesitate to monopolize the permissions of the manual disposal process.
Of course, Android hides process details, not deliberately, but naturally. If we call traditional applications process-oriented development, we are doing component-oriented development in Android. From the previous content, we can know that the redirection and communication between Android components are performed on the premise of third-party intervention, in this way, two components are generally not directly connected (service-based communication does not require third-party intervention. Therefore, Android assumes that all components form a process boundary and communicate with each other based on rpc. In this way, to cover up process details ...), it is not important to determine whether to cross the process boundary. Therefore, if developers need to pay attention to the process at this time, it will become very strange and confusing. Simply put, Android will host all the processes together, the upper layer does not need to know the process's life and death and communication details.
At the underlying layer of Android, a process constructs a running pool at the bottom, not only the activity components in the task, but also the three other components service, content provider, and broadcast aggreger, all are running in a process at the underlying layer. Here, a process is more like a resource pool (the concept is like a thread pool. It is good to retrieve a resource pool when the upper layer is used, rather than paying attention to the specific one ...), it is only to carry the running of each component, but they do not care about the direct logical relationship between each component. However, we can imagine that, to ensure integrity, Android certainly tends to throw components of the same task and application into the same process by default. However, for efficiency considerations, android allows developers to configure it.
In Android, the overall <Application> (will affect each of the components ...) you can set the <process> attribute for each component. components with the same <process> attribute are thrown to the same process for running. The most common application scenario is to configure the process attribute of <Application> to plug different applications into a process so that they can coexist. In addition, components that often communicate with a service component are put into the same process, because communication with the service is intensive, RPC is adopted, and the overhead is not small. Through configuration, it can be directly referenced in the process, which consumes a small amount.
In addition to the <process> attribute, different components have some special configuration items. Take the content provider as an example (use the <provider> item to configure ...). <Provider> the entry has a mutiprocess attribute. The default value is false. This means that content provider constructs an instance only in the process where the application that provides this component is located, third parties need to transmit data through rpc. This mode is suitable for scenarios with high construction overhead and low data transmission overhead, and may improve the cache performance. However, if you want to improve the efficiency of data transmission, you need to set mutiprocess to true, content Provider constructs an instance in each process that calls it to avoid overhead of Process Communication.
Since the Android system helps developers host processes, a complete set of algorithms are required to execute the collection logic. The Life and Death of various processes in Android are closely related to the components running on Android. Process members are assigned to a priority system according to the features of the components on Android. When the process needs to be recycled, from low priority to high priority. The android process has five priorities: foreground process, visible process, service process, background process, and empty process. As the name suggests, it is not difficult to see that the more closely connected with user operations, the more interaction with users, the higher the priority, the more difficult it is to be recycled. For more information, see Guide/topics/fundamentals.html # proclife.
With priority, you also need a good recovery time. Early recovery, low cache hit probability may lead to the destruction process of the constantly creating process, and the advantages of the pool are lost; the recovery is too late, the overall overhead is large, and the system operation efficiency is reduced, A good Ferrari may be ruined into a QQ car. For android process recycling, the most important thing is to consider the memory overhead, power and other resources. In addition, the number of components carried by each process, the number of processes opened by a single application, and other indicators, it is also an important indicator of measurement. In addition, some running time overhead is also strictly monitored, and slow processes are forced to kill. Android regularly checks the preceding parameters, and tries to recycle the components at some time points that are likely to occur.
From the perspective of user experience, the android process mechanism has a very gratifying aspect. Some programs start slowly, but with plenty of resources, you can quit and use it again and again, the startup becomes extremely fast (the process is not dead, but the frontend is obtained from the background), thanks to process hosting. Of course, the other aspect is sadly. The Android hosting algorithm also shows its childish side from time to time. It is clear that users have obviously felt that the operating speed of the operating system has dropped, open the task manager and you can see that one app is still jumping, you must manually help them end their lives to find the grave, which makes the task manager basically a necessary installation software for Android.
From the perspective of development, the process mechanism of Android frees developers. Developers do not have to worry about building a background process to secretly listen to a specific time, and try to use various daemon means to forge their own processes as if they were not dead, the issue of process life and death is already working in the scope that ordinary developers need to manage. At the same time, as with the controversy over GC and human memory management, all developers do not believe that algorithms can be more efficient than themselves. However, I have always believed that all efficiency advantages will disappear with the continuous improvement of the algorithm hardware. Only the simplicity of the development model will not change with time.

Component lifecycle
Any changes in the architecture will lead to changes in the upper-layer development mode. The process model of Android does not require developers to pay close attention to the creation and destruction of processes, however, you still need to pay attention to the influence of these time points on components. For example, you may need to save the content written to the memory to the hard disk before the process is destroyed. This requires you to pay attention to the events that occurred before the process exits.
In Android, to grasp these time points, you must understand the components lifecycles ). The life cycle of a component means that when a component is switched between the front and back ends, is created and exited by the user, and is recycled by the system, some events are notified to the corresponding component, developers can selectively handle these events to complete some additional work at the corresponding time point.
In addition to content provider, other components have the concept of lifecycle. They all need to handle some situations at regular points according to this model. For details, see Guide/topics/fundamentals.html # lcycles. Here, the thief captures the king first and uses the activity as a model.

Continue to steal the image from the SDK. A natural activity's life journey begins with oncreate and ends with ondestroy. However, when the components are in the background when the system needs them, the process may be recycled at any time, this makes it very important to know the background.
When a component enters the top of the stack and interacts with the user, the onresume function is called. Similarly, when the component exits the top of the stack, the onpause function is called. Onresume and onpause can handle many things. The most common thing is to read and write some files or set items. This is because when the component is no longer running on the frontend, other components may need to read and write the same file and settings. If onresume is no longer used for Refresh, it may be a copy of dirty data (of course, the specific situation also requires specific analysis. If the file will not be read and written by multiple users, you can put it in oncreate for reading ).
In addition to the aforementioned issue that will be harassed by other components in the background, it is also a terrible thing. In Android, there are two common methods for components to die. One is to die naturally. For example, if the stack element ABC is changed to AB, the C component will naturally die out. This kind of death is as light as a fortune, so you don't need to worry about it. But in another case, it is recycled by the system. It is like a dead man who gives up for the country.
However, this death saving method is confusing for users. Imagine a game that cannot be stored in a disk. You have been playing it for a long time, and you haven't been in close eye for three days or nights. At this time, you mm called to encourage you, and you made persistent efforts to prepare for it, however, I found that your game process was recycled by the system after it was switched to the backend. I went back to liberation three days ago and tried to become a bubble. Would you want to kill the game players or not, yes. At this time, if there is no activity life cycle, game programmers must be killed and become the scapegoat for Android. However, Android components have a life cycle. If this happens, do not hesitate to kill development programmers.
To escape, programmers have a gold medal free, that is, the android State mechanism. The so-called State means that developers store some currently running state information in a bundle object, which is a set of serializable key-value pairs. If the process of the activity component needs to be recycled, the android core will persistently store the bundle object of the activity component on the disk. When the user returns to the activity, the system will reconstruct the component, and restore the bundle object that persists to the disk. With such persistent state information, developers can distinguish specific dead methods and have the opportunity to restore the dead activity to its dead state. What developers should do is to use the onsaveinstancestate function to maintain the status information (by default, the system control will save the relevant status information, such as textview, will Save the current text information, which does not require developers to worry about ...), write to the bundle object, and then read and restore relevant information (oncreate, onstart, can also process...) in the onrestoreinstancestate function ...).

Thread
Reading data and processing in the backend, these cool guys will naturally be involved by threads. At the scheduling level of the android core, it focuses only on processes. The construction and processing of each component is done on the main thread of the process, this ensures that the logic is simple enough. Multithreading is often required by developers.
Android threads are also implemented by deriving Java thread objects and implementing the run method. However, when a user needs to run a thread with a message loop, Android provides better support, from handler and logoff. Handler transfers and distributes messages, and derives its handlemessage function to process various received messages, which is similar to win development. A logoff task is to construct a loop, waiting to exit or wait for other messages to come. On the logoff SDK page, there is a standard example of implementation of the message loop thread. Of course, a more standard method may be to construct a handlerthread and pass its logoff to handler.
In Android, the use of content providers is often linked to threads. Who makes it relevant to data. As mentioned above, content provider only provides synchronous calling interfaces to maintain more flexibility. It is a common operation to add, delete, modify, and query content providers asynchronously, android provides an asynchronous interface through the asyncqueryhandler object. This is a sub-class of handler. developers can call the startxxx method to initiate an operation. By deriving the onxxxcomplete method, they can wait for the callback after the execution to complete the entire asynchronous call process, which is very simple and clear.

Implementation
The core implementation of task and process management is in activitymanagerservice. As mentioned in the previous article, intent Parsing is the responsibility of activitymanagerservice. In fact, it is a very well-known class, because although the name is activity's Manager service, it is under its jurisdiction, it is not just activity, but also three other types of components and their processes.
Activitymanagerservice has two types of data structures: arraylist and hashmap. Activitymanagerservice has a large number of arraylists. Each component has multiple arraylists for state-based storage. Scheduling work is usually taken out from an arraylist, finding a method to tune it, and then throwing it into another arraylist. When this component has no corresponding arraylist, it means it is not far from death. Hashmap is because a component needs to be located by name or intent information, such as content provider. Its search is based on Uri. With hashmap, everything goes smoothly.
Activitymanagerservice uses the data structure named xxxrecord to express each surviving component. As a result, historyrecord (history, which stores activity information, is relative to the task stack...), servicerecord, broadcastrecord, contentproviderrecord, taskrecord, processrecord, and so on.
It is worth noting that taskrecord is the concept of a task stack. In fact, the real underlying layer does not maintain an activity stack in taskrecord. In activitymanagerservice, the activities of each task are stored in an arraylist in the form of historyrecord. Each historyrecord stores the reference of taskrecord. When an activity is executed and exits from the conceptual Task Stack, Android scans historyrecord of the same taskrecord from the current historyrecord position. This design makes the implementation of many task systems that seem to have complex logic on the upper layer uniform, concise, and commendable.
Processrecord is the core of the whole process hosting implementation. It stores information about all components running on this process. Based on this information, the system has a complete set of algorithms to determine how to deal with this process, if you are interested in recycling algorithms, you can start with the trimapplications function of activitymanagerservice.
For developers, understanding this part of implementation is mainly to help them understand the concept of the entire process and task. If you think this is clear, you don't need to touch activitymanagerservice.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.