2017-07-25 152 views
1

我是Android的初学者。Android视图 - 什么是自动保存和恢复活动

在Android中,一些泛型元素可以在onSaveInstanceState/onRestoreInstanceState中自动保存/恢复。

例如,EditText上保存/恢复的Text属性的RatingBar保存/恢复等级属性...

我从一些测试看看,但我不能找到文档中没有谈到这个。

我的问题:

我怎么知道什么是保存/恢复没有我的干预?

例如,在哪里可以找到EditText.Text自动保存/恢复?

我确切我不想测试所有属性。从JRG答案

编辑:

https://developer.android.com/guide/components/activities/activity-lifecycle.html

保存您的活动状态当你的活动开始,停止, 调用的onSaveInstanceState()方法< ...>默认实现系统该方法的 保存关于 活动的视图层次的状态的瞬态信息,例如EditText小部件中的文本或ListView的滚动位置wi DGET。

我如何知道保存/恢复的默认实现?

第二个编辑重读后JRG答案:

默认情况下,系统采用Bundle实例状态,以节省约>在活动布局每个视图对象(如文本值进入>一个EditText信息小部件)。

默认实现保存/恢复元素视图的所有状态。

回答

2

Android文档解释了关于保存状态和关于在活动和片段中保存状态的非常好的文章。

保存和恢复活动状态有些情况下,你的活动是由于正常的应用程序的行为摧毁了几个方案,比如当用户按下“后退”按钮,或者您的活动通过调用finish()方法来标记自己的销毁。如果活动处于停止状态并且很长一段时间未使用活动,或者前台活动需要更多资源,系统还可能销毁包含活动的进程以恢复内存。

当您的活动因用户按下“后退”或活动自行完成而被销毁时,该活动实例的系统概念将永远消失,因为该行为表示活动不再需要。但是,如果系统由于系统限制(而不是正常的应用程序行为)而破坏了活动,那么虽然实际的活动实例已经消失,但系统会记住它已存在,因此如果用户导航回它,系统会创建一个新的使用一组保存的数据描述活动在销毁时的状态。系统用于恢复先前状态的已保存数据称为实例状态,是存储在Bundle对象中的键值对的集合。

默认情况下,系统使用Bundle实例状态来保存有关活动布局中每个View对象的信息(例如输入到EditText小部件中的文本值)。 因此,如果您的活动实例被销毁并重新创建,那么布局的状态将恢复到之前的状态,而您不需要任何代码。但是,您的活动可能包含更多想要恢复的状态信息,例如跟踪用户活动进度的成员变量。

保存您的活动状态 当你的活动开始,停止,系统调用的onSaveInstanceState()方法,因此您的活动可以保存状态信息与键值对的集合。此方法的默认实现可以保存有关活动视图层次结构状态的瞬态信息,例如EditText小部件中的文本或ListView小部件的滚动位置。你的应用应该在onPause()方法之后和onStop()之前实现onSaveInstanceState()回调。不要在onPause()中实现此回调。

警告:您必须始终调用onSaveInstanceState()的超类实现,以便默认实现可以保存视图层次结构的状态。

要保存活动的其他状态信息,必须重写onSaveInstanceState()并将键值对添加到在您的活动意外销毁的事件中保存的Bundle对象。例如:

static final String STATE_SCORE = "playerScore"; 
static final String STATE_LEVEL = "playerLevel"; 
... 


@Override 
public void onSaveInstanceState(Bundle savedInstanceState) { 
    // Save the user's current game state 
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore); 
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel); 


    // Always call the superclass so it can save the view hierarchy state 
    super.onSaveInstanceState(savedInstanceState); 
} 

注意:为了让Android系统以恢复您的活动的意见的状态,每个视图必须有一个唯一的ID,由机器人提供:id属性。

要保存持久数据(例如用户首选项或数据库数据),当您的活动处于前台时,应该采取适当的机会。如果没有这样的机会出现,您应该在onStop()方法中保存这些数据。

恢复您的活动状态 当您的活动被重建后,先前被破坏,可以从捆绑恢复保存的状态,该系统传递到您的活动。 onCreate()和onRestoreInstanceState()回调方法都会收到包含实例状态信息的相同Bundle。

因为无论系统是在创建活动的新实例还是重新创建前一个实例,都会调用onCreate()方法,您必须在尝试读取之前检查状态Bundle是否为null。如果它为空,那么系统正在创建一个活动的新实例,而不是恢复之前被销毁的实例。

例如,下面的代码片段展示了如何在的onCreate()恢复了一些状态数据:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); // Always call the superclass first 


    // Check whether we're recreating a previously destroyed instance 
    if (savedInstanceState != null) { 
     // Restore value of members from saved state 
     mCurrentScore = savedInstanceState.getInt(STATE_SCORE); 
     mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); 
    } else { 
     // Probably initialize members with default values for a new instance 
    } 
    ... 
} 

相反的onCreate()中恢复状态,你可以选择实施onRestoreInstanceState (),系统在onStart()方法之后调用。该系统调用onRestoreInstanceState()只如果有恢复已保存的状态,这样你就不会需要检查包是否为空:

public void onRestoreInstanceState(Bundle savedInstanceState) { 
    // Always call the superclass so it can restore the view hierarchy 
    super.onRestoreInstanceState(savedInstanceState); 


    // Restore state members from saved instance 
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE); 
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); 
} 

注意:始终调用父类实现onRestoreInstanceState的( ),所以默认实现可以恢复视图层次的状态。

+0

从你的答案,我已经编辑我的问题。谢谢。 – Orwel

+0

查看我的第二个答案,提供更多详细信息和代码,以解释什么数据可以免费保存,哪些数据需要您编码!如果解释,请接受答案并投票! – JRG

+0

我不好,你回应我的问题。感谢JRG。 – Orwel

0

这里是解释一个例子...

  • 什么默认情况下,如何保存?
  • 什么数据需要您添加代码才能保存?

我创建了一个简单的android项目,它总共有4个数据点,在应用程序生命周期的某个时间点有一些值。

  1. 活动内部变量saveMe
  2. 活动内部变量saveMeNot
  3. 视图的EditText上withid(有机器人:ID)
  4. 视图的EditText上(没有机器人:ID)

这里是截图中的事件序列。

  1. 启动Android应用程序
  2. 点击SAVE按钮设定值内部变量saveMesaveMeNot。将显示一个Toast它保存了这两个变量的值。
  3. 在编辑文本中输入一些文本,如Hello和Hi。这将在编辑文本中设置文本。
  4. 旋转屏幕即方向改变。以下将会发生......
    • Android将保存在activity_main.xml中定义的所有视图的值android:id。这里只有Hello会被保存为EditText,其中输入的Hello有一个android:[email protected]+id/withId。另一个具有文本Hi的EditText不会被Android自动保存,因为它没有任何android:id。这是你免费获得的(如果你的所有视图都有android:id定义)。如果您拥有扩展视图的自定义视图,那么他们也有android:id定义。
    • Android还调用onSaveInstanceState和onRestoreInstanceState,它使您能够存储活动的所有内部变量的状态,即saveMesaveMeNot。你必须为它编码,否则状态就会丢失。就像在我的例子中,我已经保存了saveMe的状态,而不是saveMeNot。这是你不能免费获得的东西,即你必须为它编码。
  5. 点击CLICK ME按钮查看saveMesaveMeNot的价值观,你会看到,因为它是在onSaveInstanceState救了你和检索的步骤

    onRestoreInstanceState

序列仅显示saveMe

enter image description here

代码

AndroidManifest.xml中

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="test.saveinstance"> 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:roundIcon="@mipmap/ic_launcher_round" 
     android:supportsRtl="true" 
     android:theme="@style/AppTheme"> 
     <activity android:name=".MainActivity"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

MainActivity.java

package test.saveinstance; 

import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.Toast; 

public class MainActivity extends AppCompatActivity { 

    // will save in bundle in onSaveInstanceState 
    private int saveMe; 

    // will not save in bundle in onSaveInstanceState 
    private int saveMeNot; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     // do some action that generates values for 
     // activity specific variables i.e. saveMe 
     // and saveMeNot 
     Button saveButton = (Button) findViewById(R.id.save); 
     saveButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       saveMe = 10; 
       saveMeNot = 20; 
       Toast.makeText(getApplicationContext(), "SAVED: saveMe: " + saveMe + ";saveMeNot: " + saveMeNot, Toast.LENGTH_LONG).show(); 
      } 
     }); 

     // will be used to display value of 
     // saveMe and saveMeNot after orientation 
     // changes. 
     Button button = (Button) findViewById(R.id.button); 
     button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       Toast.makeText(getApplicationContext(), "DISPLAY: saveMe: " + saveMe + ";saveMeNot: " + saveMeNot, Toast.LENGTH_LONG).show(); 
      } 
     }); 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     // save saveMe in bundle 
     outState.putInt("saveMe", saveMe); 
     super.onSaveInstanceState(outState); 
     Log.d("TEST", "Saving saveMe in bundle during orientation change"); 
    } 

    @Override 
    protected void onRestoreInstanceState(Bundle savedInstanceState) { 
     super.onRestoreInstanceState(savedInstanceState); 
     // retrieve saveMe from bundle 
     saveMe = savedInstanceState.getInt("saveMe"); 
     Log.d("TEST", "Retrieving saveMe in bundle during orientation change"); 
    } 
} 

activity_main.xml中

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="test.saveinstance.MainActivity"> 

    <EditText 
     android:id="@+id/withId" 
     android:layout_marginTop="30dp" 
     android:layout_width="match_parent" 
     android:layout_height="70dp" 
     android:gravity="center" 
     android:hint="Type Here (has android:id)" /> 

    <EditText 
     android:layout_below="@id/withId" 
     android:layout_marginTop="20dp" 
     android:layout_width="match_parent" 
     android:layout_height="70dp" 
     android:gravity="center" 
     android:hint="Type Here (doesn't have android:id)" /> 

    <Button 
     android:id="@+id/button" 
     android:layout_alignParentBottom="true" 
     android:layout_marginBottom="10dp" 
     android:text="Click Me" 
     android:layout_width="match_parent" 
     android:layout_height="50dp" /> 

    <Button 
     android:id="@+id/save" 
     android:layout_above="@id/button" 
     android:layout_marginBottom="10dp" 
     android:text="Save" 
     android:layout_width="match_parent" 
     android:layout_height="50dp" /> 

</RelativeLayout> 
+0

对不起,我的问题不清楚。一个例子。我想用'Switch'。我打开文档:https://developer.android.com/reference/android/widget/Switch.html。我在哪里可以看到保存/恢复? – Orwel