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.
In the SDKTask(Guide/topics/fundamentals.html # acttaskFor example, a task is equivalent to an application (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, simply put, isA 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 (the top component of the stack in bold) |
Click Open email application to enter the inbox (Activity) |
A |
Select an email and click View Details (Activity B) |
AB |
Click "reply" to start writing a new email (Activity C) |
ABC |
A few lines of words are written. Click "select contact" to go to the "select contact" Page (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 the inbox |
A |
Exit the 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 beActivity provider(Through the configuration file...) andActivity user(Use Flag Information in intent...) for configuration and selection. 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), The way to implement the task mode configuration of the two is very clear, and I will explain some of them (the complete configuration items must be checked by the SDK, the following are some of the frequently used items ...). The provider configures components throughConfiguration File(Manifest)<Activity>And the caller usesFlag of the intent objectMake a decision. 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 developersLaunchmodeAttribute. It has four modes :"Standard","Singletop","Singletask","Singleinstance".Standard ModeIs the default and standard task mode. Without the influence of other factors, the activity that uses this mode constructs an activity instance and adds it to the caller's task stack, the standard mode is undoubtedly the most suitable for activities with average usage frequency and overhead, because its logic is simple and clear, so it is the default choice. WhileSingletop Mode, Basically the same as standard, only in the requested ActivityLocated 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 activity on the top of the stack. The activity on the top of the stack can be reloaded.OnnewintentTo handle the new intent (of course, you can ignore ...). 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 the browser bookmarks activity (BrowserbookmarkpageIs 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, At most one instance exists, and is located inTask 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,SingleinstanceMore extreme. In most cases, singleinstance and singletask are exactly the same. The only difference is that the singleinstance activity is in its stack.Only one activityIf other activities involved 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 practices, I triedYoudao dictionaryOfQuick word ActivityI have used it 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>TaskaffinityAnd 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. Only whenAllowtaskreparen TingSet to true, or add the intent flag to the caller.Flag_activity_new_taskProperty takes effect. 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.
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 applicationsProcess-oriented developmentIn Android, what we do isComponent-oriented development. From the previous content, we can know that the redirection and communication between Android components are both inThird-party interventionBecause of this intervention, the two components are generally not directly linked (for service communication, there is no need for third-party intervention, therefore, Android assumes all of them as traversing process boundaries and unified RPC-based communication. This is also used to conceal 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, the process constructsRunning poolNot only are the activity components in the task, but also the other three components service, content provider, and broadcast aggreger.BoardingRunning in a process at the underlying layer. Here, the process is more likeResource Pool(The concept is like a thread pool. It is good to retrieve one 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. But we can imagine that, to ensure integrity, Android certainly tendsThe components of the same task and application are thrown into the same process.But of course, Android allows developers to configure it out of efficiency considerations. In Android, the overall<Application>(Will affect each of the components...) and the following components can be set<Process>Attribute, components with the same <process> attribute will be thrownSame Process. 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 additionService ComponentsCommunication components 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, low Consumption. In addition to the <process> attribute, different components have some special configuration itemsContent ProviderFor example<Provider>...). <Provider> There IsMutiprocessThe default value is false, which means that the content provider is only applicable to applications that provide this component.Process to construct an instanceThird 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 every process that calls it,Avoid process communication overhead. 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. processes are grouped into onePriority System, From low priority to high priority when recycling is required. The android process has five priorities:Foreground Process,Visible Process,Service Process,Background Process,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 need to have a goodRecovery 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. Android process recycling, the most important thing is to considerMemory overheadAnd other resources such as power, in addition, the number of components carried by each process, the number of processes opened by a single application, etc.Quantity indicatorIs also an important indicator of measurement. In addition, someTime overheadIs also strictly monitored, and slow processes are forced to kill. Android ConferenceTimed checkThe preceding parameters areTime when process recovery may occurFor example, you can try to recycle a component after it is executed. 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. But I have always believed that,The advantages of all efficiency will disappear with the continuous improvement of the algorithm hardware. Only the simplicity of the Development Mode will not change with time..
Any architectural changes in the component life cycle will lead to changes in the upper-layer development mode. The android process model 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, you must understand these time points.Component lifecycle(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 a specified point according to this model. For details, refer: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 life journey, fromOncreateStart,OndestroyExtinction. 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 the component enters the top of the stack and starts to interact with the user, it will callOnresumeFunction. Similarly, when you exit the top of the stackOnpauseThe 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 to terminate a component:Natural extinctionFor 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 caseSystem RecoveryThat is the same as the treasure of death. 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 from death, that is, AndroidState mechanism. The so-called State means that developers store some of the currently running state information in oneBundleIn the object, this isSerializable key-value pair set. If the process of the activity component needs to be recycled, the android core will use the bundle object of the activity component.Persistent to diskWhen the user returns to the activity, the system will re-construct the component and restore the bundle object persistent 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 isOnsaveinstancestateThe function stores the status information to be maintained (by default, the system control automatically saves the status information, such as textview, and saves the current text information, this does not require developers to worry about ...), write to the bundle object, and thenOnrestoreinstancestateFunction to read and restore relevant information (Oncreate,Onstart, You can also process ...).
Thread
Reading data and processing in the backend, these cool guys will naturally be involved by threads. At the scheduling layer of the android core, it focuses only on processes. The construction and processing of each component isMain thread of the processThis ensures that the logic is simple enough. Multithreading is often required by developers. Android threads are also derived from JavaThreadObject To implementRunMethod. However, when a user needs to run a thread with a message loop, Android provides better support fromHandlerAndLogoff. Handler transfers and distributes messages, and derivesHandlemessageFunction, which can 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 message loop thread implementation. Of course, a more standard method may be to constructHandlerthreadThread to pass its logoff to handler. In Android,Content ProviderIs often linked to the thread. Who makes it related 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, androidAsyncqueryhandlerObject that provides an asynchronous interface. This is a subclass of handler. developers can callStartxxxMethod to initiate an operation.OnxxxcompleteMethod, wait for the callback after the execution to complete the entire asynchronous call process, which is very simple and clear.
Implementation
Core Implementation of task and process managementActivitymanagerservice. 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. In activitymanagerservice, there are two types of data structures that are most eye-catching. One isArraylistAnd the other isHashmap. 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 some namesXxxrecordTo express each surviving component. So there is,Historyrecord(The reason for saving activity information is history, which is relative to the task stack ...),Servicerecord,Broadcastrecord,Contentproviderrecord,Taskrecord,ProcessrecordAnd 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 the collection algorithm, you can useTrimapplicationsStart with the function. 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.