Data management
For read-only data, a common management pattern is to load the data in the OnCreate function until the component's Ondestory function is invoked.
// 缓存只读的数据 private Object readOnlyData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 读取数据到内存 readOnlyData = readOnlyData(); } private Object readOnlyData() { return null ; } @Override protected void onDestroy() { super.onDestroy(); // 将数据置空,加速回收 readOnlyData = null ; }
If the data supports read and write operations, it needs to be read in either Onresume or OnCreate, and the storage is implemented in OnPause.
Because when the OnPause function is called, the interface component is in a recyclable state. When resources are strained, the system forcibly destroys the Component object.
All non-persisted modifications in the object are lost. Examples of models for read-write data processing are:
// 缓存可读写的数据 private Object data; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 读取数据到内存 data = readData(); } @Override protected void onResume() { super.onResume(); data = readData(); } private Object readData() { // TODO 读取数据 return null ; } private void writeData(Object data) { // TODO 写入数据 } @Override protected void onPause() { super.onPause(); writeData( data); } @Override protected void onDestroy() { super.onDestroy(); // 将数据置空,加速回收 data = null ; }
State management
The Onsavainstancestate function is called first when the system cuts the interface component away from the foreground state (that is, before the OnPause function call). In this function, the developer can tell the state data in the component to the Outstate object of the parameter. The object type of outstate is bundle, which is the storage of data by means of key-value pairs.
oncreate--If the state data is included, the onrestoreinstancestate is called first. The recovery data is called before the
onrestoreinstancestate--component enters the foreground state. The
onsaveinstancestate--component leaves the foreground state and calls the state to save the data before calling OnPause. If the user is actively leaving the foreground state, the state is not triggered.
Boolean needsavedraft = true; If it is not active, it calls Onsaveinstancestate @Override protected void onsaveinstancestate (Bundle outstate) {Super . Onsaveinstancestate (Outstate); Save the modified state first to restore the information at startup Outstate.putboolean ("Need_save_draft", Needsavedraft); Indicates that there is no need to save Needsavedraft = false on passive exit; } @Override protected void Onrestoreinstancestate (Bundle savedinstancestate) {Super.onrestoreinstancestat E (savedinstancestate); if (savedinstancestate! = null) {Needsavedraft = Savedinstancestate.getboolean ("Need_save_draft"); }} @Override protected void OnPause () {super.onpause (); If it is not a passive push, ask the user if (Needsavedraft) {showasksavedraftdialog (); }} private void Showasksavedraftdialog () {//TODO auto-generated method stub}
After the current onsaveinstancestate function call is complete, the data in the Outstate object that stores the state information is kept by the system process, regardless of whether the application process is reclaimed by the system, and the data is not lost.
If Savedinstancestate is empty, it means that this is a completely new construct and the reverse is a restorative construct. The interface component can use the information in this parameter to restore the interface state to the state it was before the system was reclaimed.
Distinguishing between a restorative construct or a new puppy is a detail that needs to be handled properly in development. In the case of a new construct, the interface component needs to parse the intent object sent by the call, control the orchestration, and if it is a restorative construct, it needs to restore the last cached information one by one.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { needSaveDraft = savedInstanceState.getBoolean("NEED_SAVE_DRAFT" ); } else { // TODO 解析Intent对象传入的参数或者Action // Intent intent = getIntent(); // intent.getBundleExtra(""); } }
To reduce the burden on developers, most system controls in Android implement the logic of State caching. Before the Onsaveinstancestate function is called, the interface component traverses the entire control tree, saving the individual controls. Wait until the Onrestoreinstancestate function is called for recovery.
If the system's built-in control state cache logic does not meet the developer's needs, developers can call the view.setsaveenabled function to turn off automatic caching of the corresponding control object and manage the control's state in the Onsaveinstancestate function.
Onsaveinstancestate and onrestoreinstancestate for state management do not belong to the basic life cycle functions, but the operation of state management is necessarily related to the life cycle of the component, and developers also need to make good use of these functions. Deal with changes caused by life cycle changes.
Registration Management
interface components in the process of user interaction sometimes need to update the information as the system state changes in a timely manner. such as address information.
Interface components can capture these changes by listening for relevant event information. If the event being listened to changes, only when the component in the foreground state to take effect (such as broadcast event monitoring, geographical changes, etc.), you need to register in the early Onresume, log off in OnPause.
LocationManager mLocationManager; LocationListener mLocationListener; @Override protected void onResume() { super.onResume(); mLocationManager.requestLocationUpdates(provider, minTime, minDistance, listener ); } @Override protected void onPause() { super.onPause(); mLocationManager.removeUpdates(mLocationListener ); }
Thread Management
In the application development, the network communication, the data operation, the complex computation and so on all need to spend a lot of time, therefore the application often needs to adopt the multi-threaded design pattern, executes this kind of time-consuming operation in the background thread.
The Android component life cycle is a typical synchronous processing logic. There is not a good support model for multithreaded architectures. This requires the developer to make full use of the component's life cycle and to properly arrange the construction and destruction of the threads according to their own needs.
If the thread's life cycle is closely related to the component's life cycle, it needs to be managed in the interface component lifecycle, and once the thread is constructed by the interface component, it needs to be explicitly terminated in ondestory and its thread space reclaimed. Otherwise, it causes a thread resource leak.
However, only the ondestory recovery thread is still not perfect, because in the case of resource constraints, the system will forcibly reclaim the component, at which point the component's Ondestory function may not be called, resulting in thread resource leaks.
A better thread management scenario is to cache the handle information of the thread as the state information of the interface component. If the system forcibly reclaims the object component, it is necessary to find the thread based on the cached thread handle when the component is constructed again, thus avoiding thread leaks.
Static final String thread_worker_id = "thread_id";
Thread Workerthread;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { long threadId = savedInstanceState.getLong(THREAD_WORKER_ID); workerThread = findThreadById(threadId); } else { // TODO 创建新的线程 } } private Thread findThreadById( long id) { // 完善根据线程id,找到该线程 的过程 http://bao231.iteye.com/blog/1917616?utm_source=tuicool return null ; } @Override protected void onDestroy() { super.onDestroy(); if (workerThread != null) { workerThread.interrupt(); workerThread = null ; } }
Life cycle of service components
The use of services can be divided into two types, namely the invocation of services and binding services. These two different ways of using the life cycle are slightly different.
However, regardless of the usage mode, the component's life cycle starts from OnCreate and ends in Ondestory. Because of the service component development, you can choose to do initialization work such as data loading in OnCreate, while doing the cleanup work such as data destruction and thread termination in Ondestory.
In binding mode, when the Onbind function is called, the description service is bound to the foreground interface component. The service component should load the resource within the function, build the communication object, and wait for the binding's call, based on the intent object passed by the caller. When the interface component completes the related operation, the binding to the serviced component needs to be lifted. At this point, the Onunbind function is called, and you can do some statistical and resource cleanup work in the function.
The process state of the serviced component being bound is closely related to the interface component that binds the service. If the binding component is a foreground interface component, the process in which the service is changed is the foreground process. The reverse is the same.
The Android system does not easily recycle foreground processes or visual processes, so components that are bound in state are not usually forced to stop. For developers, the binding service must not forget to choose the right time to contact the binding, otherwise the service component will stay in the foreground or the visual state can not be recycled, thus wasting system resources.
In invocation mode, when the serviced component executes the Onstartcommand function, the process in which the service resides is the foreground process, with the highest priority. When the Onstartcommand function finishes, if there are no related functions called stopself to stop the serviced component, the serviced component will become the backend component to continue serving until the call stopself function stops or waits for the system to be forcibly reclaimed.
The Onstartcommand function adds three return values and control parameters that specify how the background service component runs, with three of the most important return values:
The start_sticky--system is responsible for the service component, and after the component is forcibly reclaimed, the Onstartcommand function is called to restart the service when the resource is well-resourced. Until the Stopself function is called. For developers, write a return value of Start_stricky, be sure to call the Stopself function at the appropriate time to actively shut down the service, otherwise it will consume system resources indefinitely.
The start_not_sricky--indicates that the system can reclaim the component unconditionally without having to pay attention to whether the service is complete or not responsible for restarting the service.
start_redeliver_intent--means that the service component needs to be guaranteed to complete the processing of each INTENT object.
The life cycle of a trigger component:
The life cycle of a trigger is the shortest, and its entire lifecycle is to construct a trigger object and then execute the OnReceive function. For the execution of the OnReceive function, the system immediately starts destroying the component object of the trigger, reclaiming the resources it occupies.
During the life cycle, the OnReceive function is not able to handle time-consuming tasks internally.
The life cycle of the data source component
In theory, the data source component has no so-called life cycle, so the state of the data source component is not judged by the process priority. Therefore, the system does not notify the developer of the destruction of the data source when it recycles the process resources.
However, Android will call the OnCreate function when constructing the data source component. A developer can data the database or other data content required by the data source in the function.
As a result, it is not appropriate to deploy write optimization policies in the data source component that are deferred writes, because the data source component may be silently reclaimed by the system, resulting in the loss of non-persisted write data. Therefore, in the implementation of the data source component, the Write optimization strategy should be referred to the upper call to implement, or the underlying data store to deal with.
Once the data source component is constructed, it remains in a long-running state until the process in which it resides is reclaimed by the system. So don't cache too much data in the data source component to avoid taking up memory space.
Android app General development Tips-Leveraging the component life cycle