Explore Activity Data Preservation

Source: Internet
Author: User

A problem was found in development: When I opened a activty interface through intent,
The status of the newly opened activity is lost. At that time, when I directly press home to acitvity the background, and then reopen the activity, I found that the status of activity at this time is the state before exiting. But what I'm trying to achieve now is that, no matter how you open the activity, I want him to revert to the previous acitvity state instead of opening a new activity. So in response to this phenomenon, I seek solutions.

Using Onsaveinstancestate and Onrestoreinstancestate

After discovering this problem, my first feeling was to use the Onrestoreinstancestate method in activity to read and write the saved data to the new activity when the new activity was opened. The principle of implementation is what I said earlier. Press the home button to reopen the activity to revert to the original activity state. Here I will start to explain the preservation mechanism of data in activity.

Life cycle of activity

To fully understand the storage mechanism in activity, you must be very familiar with the life cycle of the activity, and here I will briefly describe the life cycle of the acttivity. An official activity life cycle diagram is given here directly:

If you are still not familiar with the activity's life cycle, you can refer to the comments in the code behind me on the method of each activity cycle. There is not much explanation here.

The data storage mechanism in # # # Acitvity

当一个activity被paused或者stopped时,activity的状态可以被保存。 的确如此,因为 Activity 对象在paused或者stopped时仍然被保留在内存之中——它所有的成员信息和当前状态都仍然存活。 这样用户在activity里所作的改动全都还保存着,所以当activity返回到前台时(当它“resume“),那些改动仍然有效。不过,如果系统是为了回收内存而销毁activity,则这个 Activity 对象就会被销毁,这样系统就无法简单地resume一下就能还原完整状态的activity。 如果用户要返回到这个activity的话,系统必须重新创建这个Activity 对象。可是用户并不知道系统是先销毁activity再重新创建了它的,所以,他很可能希望activity完全保持原样。 这种情况下,你可以保证activity状态的相关重要信息都由另一个回调方法保存下来了,此方法让你能保存activity状态的相关信息: onSaveInstanceState()。在activity变得很容易被销毁之前,系统会调用 onSaveInstanceState()方法。 调用时系统会传入一个Bundle对象, 你可以利用 putString() 之类的方法,以键值对的方式来把activity状态信息保存到该Bundle对象中。 然后,如果系统杀掉了你的application进程并且用户又返回到你的activity,系统就会重建activity并将这个 Bundle 传入onCreate() 和onRestoreInstanceState() 中,你就可以从 Bundle 中解析出已保存信息并恢复activity状态。如果没有储存状态信息,那么传入的 Bundle 将为null(当activity第一次被创建时就是如此)

Here's an official picture showing the storage of the activity state.
Perhaps this would be more intuitive to represent the invocation of Onsaveinstancestate () and Onrestoreinstancestate ()

However, it is important to note that the activity data is saved only if the activity is destroyed by = = Accidental = =, and the activity that is considered to be active destruction by the user will not save the data and will not invoke the method of saving the data.

So what is the = = accidental destruction of activity?
* When the user presses the home button
* Changan Home key, run other programs
* Press the power button (turn off the screen display)
* Start a new activity from an activity a
* The screen orientation has changed

So in the above case, the activity will call Onsaveinstancestate () to save the data by default, as for the order of invocation, please refer to the previous picture. 、

in this case, you have to say the rewrite Onsaveinstancestate () method.
If you need to save additional data, you need to overwrite the Onsaveinstancestate () method. It is important to note that the Onsaveinstancestate () method is only suitable for storing transient data, such as the state of the UI control, the value of the member variable, and not the persisted data, which should be persisted when the user leaves the current activity at OnPause () (for example, saving data to a database or file). In this case, it is important to understand that it is not suitable for storing more time-consuming data in OnPause ().
Because the Onsaveinstancestate () method method is not necessarily called, it is not appropriate to persist persisted data in the method, such as inserting records into the database. The operation to save persisted data should be placed in OnPause (). If it is a permanent value, it is saved in OnPause (), and if it is large, another thread, do not block the UI thread.

Here, it seems a bit clear, so long as we show in the activity Call Onsaveinstancestate (), will soon be a good solution to this problem, so I wrote the following code, here is the content of mainactivity.

 PackageCom.create.activitydata;ImportAndroid.content.Intent;ImportAndroid.os.PersistableBundle;Importandroid.support.v7.app.AppCompatActivity;ImportAndroid.os.Bundle;ImportAndroid.util.Log;ImportAndroid.view.View;ImportAndroid.widget.CheckBox;ImportAndroid.widget.EditText;/** * Test to save data in activity */ Public  class mainactivity extends appcompatactivity {    PrivateEditText EditText;PrivateCheckBox checkbox;Private Static FinalString TAG ="Mainactivity";@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);        EditText = (editText) Findviewbyid (R.id.text);    checkbox = (checkbox) Findviewbyid (R.id.check); }/** * The activity is stopped and then called before it is started again. The next callback method is always onstart () */    @Override    protected void Onrestart() {//Here you can manually add the UI status code to read activity        Super. Onrestart (); }/** * Activity to be called before being displayed to the user.     * If activity enters the foreground, the next callback method is Onresume (); * If you enter a hidden state, the next callback method is OnStop (). */    @Override    protected void OnStart() {Super. OnStart (); }/** * Activity begins to be called before the user interacts.     The activity is at the top of the activity stack, where the user can enter it.     * The next callback method is always OnPause (). */    @Override    protected void Onresume() {Super. Onresume (); }/** * Called when the system is ready to start another activity that is recovering. This method is commonly used to submit unsaved changes as permanent data, stop animation, and other tasks that may consume CPU.     It should complete the work very quickly, because the next activity will not be resumed until this method returns. * If the activity returns to the foreground, the next callback method is Onresume (), and if the user is not visible, the next one is OnStop () */    @Override    protected void OnPause() {Super. OnPause ();//Here you can add data that is time consuming and requires long-lasting retention. }/** * Called when activity is no longer visible to the user.     The reason may be that it is about to be destroyed, or that other activity (existing or new) * is resumed and will overwrite the activity. * If activity returns to interacting with the user, the next callback method is Onrestart (); If the activity is about to disappear, the next callback method is OnDestroy () */    @Override    protected void OnStop() {//Add code to save activity status here        Super. OnStop (); }@Override    protected void OnDestroy() {Super. OnDestroy (); }/** * Read Data * Two methods for reading and storing activity status are not in the activity life cycle * But when the activity stops unexpectedly, the system calls the default method to save the current state, and the next time the activity is opened Call Onsaveinstancestate to revert to its original state * /    @Override    protected void onrestoreinstancestate(Bundle savedinstancestate) {Super. Onrestoreinstancestate (Savedinstancestate); LOG.E (TAG,"Onrestoreinstancestate"); }/** * Save data * @param outstate * @param outpersistentstate * *    @Override     Public void onsaveinstancestate(Bundle outstate, Persistablebundle outpersistentstate) {Super. Onsaveinstancestate (Outstate, outpersistentstate); LOG.E (TAG,"Onsaveinstancestate"); } Public void Tonext(View view) {Intent Intent =NewIntent (mainactivity. This, Nextactivity.class);    StartActivity (Intent); }}

But here I would like to say, I have tried for a long time not to show the call Onsaveinstancestate () These methods, the source code in the activity is not much understanding, so I gave up to use this method to restore the status of the activity
(PS, by the way, in addition, only the ID of the control call Onsaveinstancestate () to save the normal, otherwise it will fail, as to how to invalidate this method, you can set the android:saveenabled to "false", or call the Setsaveenabled () method)

Using the activity's startup mode

After the failure of the above method, I need help from others. The idea is that when using intent to open an activity that has already been opened, there is no need to re-create a new activity, but to open the activity immediately before. Think of this, Huanran Dawu: This I can directly use the activity of the starting mode of current affairs activity has been on the top of the stack, when opening him, directly open it instead of new activity. This is the perfect solution to my problem. Just one line of code.

There are only four startup modes of activity:
* Standard
Standard is the active default startup mode, which is automatically used by all activities without explicit designation. In standard mode (that is, by default), whenever a new activity is started, it is placed in the stack on the return stack and at the top of the stack. For activities that use standard mode, the system does not care if the activity is already present in the return stack, and a new instance of the activity is created each time it is started.

* Singletop
When the active startup mode is specified as Singletop, if it is found that the stack at the top of the return stack is already active at the start of the activity, it is considered that it can be used directly and no new activity instances will be created.

* Singletask
Using the Singletop mode is a good solution to the problem of repeatedly creating top-of-stack activities, but as you can see in the previous section, if the activity is not at the top of the stack, more than one activity instance may be created. So is there a way to get an activity that only has one instance in the context of the entire application? This is accomplished with the help of the Singletask model. When the active startup mode is specified as Singletask, each time the activity is started, the system first checks to see if there is an instance of the activity in the return stack, uses the instance directly if the discovery already exists, and puts all the activities on top of the activity out of the stack, creating a new instance of the activity if no discovery is found.

* SingleInstance
The activity of the SingleInstance mode enables a new return stack to manage this activity (in fact, if the Singletask mode specifies a different taskaffinity, a new return stack is also started), in which case a separate return stack is available to manage the activity. Regardless of which application accesses this activity, the same return stack is shared, and the problem of shared activity instances is resolved.

Keep a beautiful tail ~

Explore Activity Data Preservation

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.