android-activity - 在安卓保存Activity状态

  显示原文与译文双语对照的内容

我一直在使用 Android SDK,但在保存应用程序状态方面还是有点不清楚。 因此,给出了这个示例的次要 re-tooling:


package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);

 mTextView = new TextView(this);

 if (savedInstanceState == null) {
 mTextView.setText("Welcome to HelloAndroid!");
 } else {
 mTextView.setText("Welcome back.");
 }

 setContentView(mTextView);
 }

 private TextView mTextView = null;
}

我认为这可能是一个最简单的例子,但它总是给我第一条消息,不管我如何远离这个应用。 我相信这可能是简单得像重写 onPause 30分钟一次的或者类似的东西,但我一直戳到的距离在官方文档,还没有发现任何明显的情况,所以希望得到任何帮助。

让我在三,二,一个中看到一个傻瓜。

时间:

你需要重写 onSaveInstanceState(Bundle savedInstanceState) 并将要更改的应用程序状态值写入 Bundle 参数,如下所示:


@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
 super.onSaveInstanceState(savedInstanceState);
//Save UI state changes to the savedInstanceState.
//This bundle will be passed to onCreate if the process is
//killed and restarted.
 savedInstanceState.putBoolean("MyBoolean", true);
 savedInstanceState.putDouble("myDouble", 1.9);
 savedInstanceState.putInt("MyInt", 1);
 savedInstanceState.putString("MyString","Welcome back to Android");
//etc.
}

这个包实质上是一种存储 NVP ("name-value对") 映射的方法,它将被传递到 onCreate(),并在其中提取类似于以下内容的值:


@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
 super.onRestoreInstanceState(savedInstanceState);
//Restore UI state from the savedInstanceState.
//This bundle has also been passed to onCreate.
 boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
 double myDouble = savedInstanceState.getDouble("myDouble");
 int myInt = savedInstanceState.getInt("MyInt");
 String myString = savedInstanceState.getString("MyString");
}

你通常会使用这里技术来存储应用程序( 选择,未保存的文本,等等 )的实例值。

savedInstanceState 只用于保存与 Activity的当前实例相关的状态,例如当前导航或者选择信息,这样,如果安卓破坏并重新创建一个 Activity,它就会回到以前的状态。 查看 onCreateonSaveInstanceState的文档

更长时间的状态,考虑使用SQLite数据库,文件或者首选项。 查看保存持久状态

在安卓设备这,我的同事写了一篇文章来说明应用程序状态,包括家庭内部在 Activity 生命周期和状态信息,如何保存状态信息,并将内容保存到状态 BundleSharedPreferences请看一看罢。

本文介绍了三种方法:

使用实例状态包存储应用程序生存期( IE 暂时)的本地变量/用户界面控制数据


[Code sample – Store State in State Bundle]
@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
//Store UI state to the savedInstanceState.
//This bundle will be passed to onCreate on next call. EditText txtName = (EditText)findViewById(R.id.txtName);
 String strName = txtName.getText().toString();

 EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
 String strEmail = txtEmail.getText().toString();

 CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
 boolean blnTandC = chkTandC.isChecked();

 savedInstanceState.putString("Name", strName);
 savedInstanceState.putString("Email", strEmail);
 savedInstanceState.putBoolean("TandC", blnTandC);

 super.onSaveInstanceState(savedInstanceState);
}

使用共享首选项在应用程序实例( IE 永久) 之间存储局部变量/用户界面控制数据


[Code sample – Store State in SharedPreferences]
@Override
protected void onPause() 
{
 super.onPause();

//Store values between instances here
 SharedPreferences preferences = getPreferences(MODE_PRIVATE);
 SharedPreferences.Editor editor = preferences.edit();//Put the values from the UI
 EditText txtName = (EditText)findViewById(R.id.txtName);
 String strName = txtName.getText().toString();

 EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
 String strEmail = txtEmail.getText().toString();

 CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
 boolean blnTandC = chkTandC.isChecked();

 editor.putString("Name", strName);//value to store
 editor.putString("Email", strEmail);//value to store
 editor.putBoolean("TandC", blnTandC);//value to store 
//Commit to storage
 editor.commit();
}

使用保留的Non-Configuration实例在应用程序生存期内的活动之间保持对象实例处于活动状态


[Code sample – store object instance]
private cMyClassType moInstanceOfAClass;//Store the instance of an object
@Override
public Object onRetainNonConfigurationInstance() 
{
 if (moInstanceOfAClass!= null)//Check that the object exists
 return(moInstanceOfAClass);
 return super.onRetainNonConfigurationInstance();
}

当系统需要内存并杀死一个应用程序时调用 onSaveInstanceState 。 当用户关闭应用程序时,它不会被调用。 所以我认为应用程序状态应该保存在 onPause 中,它应该保存到一些持久存储,比如 Preferences 或者 Sqlite

两种方法都非常有用且有效,它们最适合于不同的场景:

  1. 使用sqlite,用户终止该应用程序和re-opens它日在后,应用程序需要重新加载最后一个会话中的数据–这需要一个持久化存储方案的应用pif等
  2. onSaveInstanceState()onRestoreInstanceState() 通常adequate,用户切换应用程序,然后回来到原来的保存和还原成组资料并且想要拿起中断处的-

如果以持久方式保存状态数据,它可以在 onResume() 或者 onCreate() ( 或者在任何生命周期调用上) 中重新加载。 这可能是或者可能不是期望的行为。 如果你将它的存储在一个套装在一个 InstanceState,那么都是瞬时的,只适合存储的数据,用于相同的用户'会话'( 我使用的术语会话松散'会话'之间),但不。

没那么重要,它只是一种方式比其他的更好,就像一切要理解哪些行为你需要并选择最适当的方法。

在我看来,保存状态是一个 kludge 。 如果你需要保存持久数据,只需使用 SQLite数据库。 安卓可以很 SOOO 容易。

像这样:


import java.util.Date;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class dataHelper {

 private static final String DATABASE_NAME ="autoMate.db";
 private static final int DATABASE_VERSION = 1;

 private Context context;
 private SQLiteDatabase db;
 private OpenHelper oh ;

 public dataHelper(Context context) {
 this.context = context;
 this.oh = new OpenHelper(this.context);
 this.db = oh.getWritableDatabase();
 }

 public void close()
 {
 db.close();
 oh.close();
 db = null;
 oh = null;
 SQLiteDatabase.releaseMemory();
 }


 public void setCode(String codeName, Object codeValue, String codeDataType)
 {
 Cursor codeRow = db.rawQuery("SELECT * FROM code WHERE codeName = '"+ codeName +"'", null);
 String cv ="" ;

 if (codeDataType.toLowerCase().trim().equals("long") == true)
 {
 cv = String.valueOf(codeValue);
 }
 else if (codeDataType.toLowerCase().trim().equals("int") == true)
 {
 cv = String.valueOf(codeValue);
 }
 else if (codeDataType.toLowerCase().trim().equals("date") == true)
 {
 cv = String.valueOf(((Date)codeValue).getTime());
 }
 else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
 {
 String.valueOf(codeValue);
 }
 else
 {
 cv = String.valueOf(codeValue);
 }

 if(codeRow.getCount()> 0)//exists-- update
 {
 db.execSQL("update code set codeValue = '" + cv +
"' where codeName = '" + codeName +"'");
 }
 else//does not exist, insert
 {
 db.execSQL("INSERT INTO code (codeName, codeValue, codeDataType) VALUES(" +
"'" + codeName +"'," +
"'" + cv +"'," +
"'" + codeDataType +"')" );
 }
 }

 public Object getCode(String codeName, Object defaultValue)
 {
//Check to see if it already exists
 String codeValue ="";
 String codeDataType ="";
 boolean found = false;
 Cursor codeRow = db.rawQuery("SELECT * FROM code WHERE codeName = '"+ codeName +"'", null);
 if (codeRow.moveToFirst())
 {
 codeValue = codeRow.getString(codeRow.getColumnIndex("codeValue"));
 codeDataType = codeRow.getString(codeRow.getColumnIndex("codeDataType"));
 found = true;
 }

 if (found == false)
 {
 return defaultValue;
 }
 else if (codeDataType.toLowerCase().trim().equals("long") == true)
 {
 if (codeValue.equals("") == true)
 {
 return (long)0;
 }
 return Long.parseLong(codeValue);
 }
 else if (codeDataType.toLowerCase().trim().equals("int") == true)
 {
 if (codeValue.equals("") == true)
 {
 return (int)0;
 }
 return Integer.parseInt(codeValue);
 }
 else if (codeDataType.toLowerCase().trim().equals("date") == true)
 {
 if (codeValue.equals("") == true)
 {
 return null;
 }
 return new Date(Long.parseLong(codeValue));
 }
 else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
 {
 if (codeValue.equals("") == true)
 {
 return false;
 }
 return Boolean.parseBoolean(codeValue);
 }
 else
 {
 return (String)codeValue;
 }
 }


 private static class OpenHelper extends SQLiteOpenHelper {

 OpenHelper(Context context) {
 super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }

 @Override
 public void onCreate(SQLiteDatabase db) {
 db.execSQL("CREATE TABLE IF NOT EXISTS code" +
"(id INTEGER PRIMARY KEY, codeName TEXT, codeValue TEXT, codeDataType TEXT)");
 }

 @Override
 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
 }
 }
}

一个简单的调用


dataHelper dh = new dataHelper(getBaseContext());
String status = (String) dh.getCode("appState","safetyDisabled");
Date serviceStart = (Date) dh.getCode("serviceStartTime", null);
dh.close();
dh = null;

我想我找到答案了。 让我告诉你我用简单的词做了什么:

假设我有两个活动,activity1和 activity2,我从activity1导航到 activity2 ( 我在activity2中做了一些工作),然后通过单击activity1中的按钮再次回到 Activity 1. 在相同工况下,当我最后一次离开现在在这个阶段我想回到 activity2,我想看到我

对于上面的场景,我所做的就是在清单中做了如下更改:


<activity android:name=".activity2"
 android:alwaysRetainTaskState="true" 
 android:launchMode="singleInstance">
</activity>

在activity1上的按钮单击事件我这样做:


Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.setClassName(this,"com.mainscreen.activity2");
startActivity(intent);

在activity2中,单击事件我这样做:


Intent intent=new Intent();
intent.setClassName(this,"com.mainscreen.activity1");
startActivity(intent);

现在会发生的是,无论我们在activity2中做了什么更改,都不会丢失,并且我们可以在前面的状态中查看 activity2.

我相信这就是答案,这对我来说很好。 如果我错了,纠正我。

真的onSaveInstance Activity callen当的,以秒为背景

从文档中引用:"方法 onSaveInstanceState(Bundle) 在将 Activity 置于这样的背景状态之前调用"

...