本文转载于:http://chengbs.iteye.com/blog/1156167

比较onsaveinstancestate() 与 onretainnonconfigurationinstance()在不同需求中的用法

很多网友可能知道android横竖屏切换时会触发onsaveinstancestate,而还原时会产生onrestoreinstancestate,但是android的activity类还有一个方法名为onretainnonconfigurationinstance和getlastnonconfigurationinstance这两个方法。



我们可以通过 onretainnonconfigurationinstance 代替 onsaveinstancestate,比如距离2



@override

public object onretainnonconfigurationinstance() 



//这里需要保存的内容,在切换时不是bundle了,我们可以直接通过object来代替

return obj;

}



在恢复窗口时,我们可以不使用 onrestoreinstancestate,而代替的是 getlastnonconfigurationinstance 方法。我们可以直接在oncreate中使用,比如



object obj = getlastnonconfigurationinstance(); 最终obj的内容就是上次切换时的内容。

针对android平台,不论出于哪种目的,都或多或少需要在多个activities中的跳转操作,其中包括为了获得某些系统资源和必要信息,而通过启动(startactivity()&startactivityforresult() )child activity来提供一个选择器或者作为用户输入信息的介质。这期间父级activity将暂时性失去焦点,从而在这之前先通过 onsaveinstancestate() 方法临时存储一些必要的信息,当父级的activity重新成为当前焦点后,系统将触发 onrestoreinstancestate()
恢复失去焦点前的原有数据!onretainnonconfigurationinstance()也具有相同的目的来处理类似的请求,其主要是由于旋转设备而更改显示模式,进而触发这个方法的调用。



那么在遇到某些特定需求时,特别是针对设备旋转后所导致的显示模式发生变化后,应该依据什么条件来判断应用哪种方式才能更好的满足需要呢?做出选择之前有必要分别了解两种方法的各自特点。



onsaveinstancestate()



在当前的activity中通过新的intent启动其它activities之后,它将通过这个方法自动保存自身的数据,当再次出返回时可以通过 onrestoreinstancestate()复原数据。另外一种情况也将调用这个方法,当旋转设备后屏幕显示模式发生改变时。需要注意的一点是整个过程完全由系统控制,无法通过onsaveinstancestate()返回一个自定义的数据。



另外,onsaveinstancestate()在所有activity destroying过程中被调用,它仅仅是为了在重新回到这个特定的activity之后,依据activity state重新创建一个与之前状态完全相同的activity。例如:当我们启动某些connection时,state并不能依然保存这个连接状态。所以当调用onsaveinstancestate后,所有当前的connection将一同销毁。当第二次通过 onrestoreinstancestate()找回之前的连接设置并重新建立新的连接实体。



如果大家有更多的发现,或者有不用于以上的验证结果,非常感谢能参与这个话题的讨论。



onretainnonconfigurationinstance()



当device configuration发生改变时,将伴随destroying被系统调用。通过这个方法可以像onsaveinstancestate()的方法一样保留变化前的activity state,最大的不同在于这个方法可以返回一个包含有状态信息的object,其中甚至可以包含activity instance本身。新创建的activity可以继承大量来至于parent activity state信息。



用这个方法保存activity state后,通过getlastnonconfigurationinstance()在新的activity instance中恢复原有状态。



这个方法最大的好处是:



* 当activity曾经通过某个网络资源得到一些图片或者视频信息,那么当再次恢复后,无需重新通过原始资源地址获取,可以快速的加载整个activity状态信息。



* 当activity包含有许多线程时,在变化后依然可以持有原有线程,无需通过重新创建进程恢复原有状态。



* 当activity包含某些connection instance时,同样可以在整个变化过程中保持连接状态。



下边是需要特别注意的几点:



* onretainnonconfigurationinstance()在onsaveinstancestate()之后被调用。

* 调用顺序同样介于onstop() 和 ondestroy()之间。



接下来将通过一个例子来简单了解onretainnonconfigurationinstance()和getlastnonconfigurationinstance()的用法。



这个例子将首先启动一个包含两个按钮的activity。其中一个按钮用于调用本地通讯录,并将所选择的某一项作为返回值传给当前 activity。另外一个按钮的作用是查看当前所选择的通讯信息。正常的流程是当第一次启动程序后,第二个查看信息按钮是不可用状态。当通过pick按钮确定选择并返回某一通讯录内容时,查看信息按钮的状态切换为可操作状态。然后当改变设备的configuration时,可以注意到即便是 activity通过oncreate()重新构建,但是之前所保证的ui属性依然保持最后一次操作的状态。



简单建立一个包含两个按钮的ui:

?view code xml



<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<button android:id="@+id/pick"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_weight="1"

android:text="pick"

android:enabled="true"

/>

如果你想保存Activity的信息(例如,类实例的变量)而又不需要和其它的组件共享的话,你可以调用Activity的getPreferences方法,不用指定一个Preference的名字。对返回的Shared
Preference的访问只限于调用的Activity;每个Activity支持一个不命名的Shared
Preference对象。



下面的框架代码显示了如何使用Activity的私有Shared
Preference:



protected void saveActivityPreferences()

{

// Create or retrieve the activity preferences object.

SharedPreferences activityPreferences = getPreferences(Activity.MODE_PRIVATE);



// Retrieve an editor to modify the shared preferences.

SharedPreferences.Editor editor = activityPreferences.edit();



// Retrieve the View

TextView myTextView = (TextView)findViewById(R.id.myTextView);



// Store new primitive types in the shared preferences object.

editor.putString(“currentTextValue”, myTextView.getText().toString());



// Commit changes.

editor.commit();

}



保存和恢复实例状态



对于保存Activity实例的变量来说,Android提供了一种替代Shared
Preference的特殊方法。



通过重写Activity的onSaveInstanceState事件处理函数,你可以使用它的Bundle参数来保存实例的值。保存数据的方法还是使用与在Shared
Preference中相同的get和put方法。在完成Bundle的修改后,将其传入父类的处理函数中,如下面的代码片段所示:



private static final String TEXTVIEW_STATE_KEY = “TEXTVIEW_STATE_KEY”;

@Override

public void onSaveInstanceState(Bundle outState) {

// Retrieve the View

TextView myTextView = (TextView)findViewById(R.id.myTextView);



// Save its state

outState.putString(TEXTVIEW_STATE_KEY,

myTextView.getText().toString());



super.onSaveInstanceState(outState);

}



这个处理函数会在Activity的Active生命周期结束时触发,但仅在它不是显式地结束(即异常结束)。因此,它一般用于确保在单个用户会话中的Active生命周期间Activity状态的一致性。



如果一个会话期间,应用程序被迫重启,那么,保存的Bundle会传入到onRestoreInstanceState和onCreate方法中。下面的片段显示了如何从Bundle中提取值来更新Activity实例的状态:



@Override

public void onCreate(Bundle icicle) {

super.onCreate(icicle);

setContentView(R.layout.main);

TextView myTextView = (TextView)findViewById(R.id.myTextView);

String text = “”;

if (icicle != null && icicle.containsKey(TEXTVIEW_STATE_KEY))

text = icicle.getString(TEXTVIEW_STATE_KEY);

myTextView.setText(text);

}



有一点很重要的是,记住onSaveInstanceState仅在Activity变成非Active状态时调用,但不在调用finish来关闭它或用户按下Back按钮时调用。



保存To-Do List Activity的状态



目前,每一次To-Do List例子程序重新启动时,所有的to-do项都丢失了且任何在文本输入框中输入的文字也被清除了。在这个例子中,你将在会话期间保存To-Do
List程序的状态。



ToDoList Activity中的实例状态由三个变量组成:



❑ 是否一个新的Item正在添加?



❑ 在新的项目输入框中存在什么样的文字?



❑ 哪个是当前选择的项目?



使用Activity默认的Shared Preference,你可以保存这些值,当Activity重启时更新UI。



在本章的后面,你将学习如何使用SQLite去保存to-do项目。这个例子是第一步,演示如何通过保持Activity实例的细节来确保无瑕疵的体验。



1. 添加静态的字符串用作Preference的键。



private static final String TEXT_ENTRY_KEY = “TEXT_ENTRY_KEY”;

private static final String ADDING_ITEM_KEY = “ADDING_ITEM_KEY”;

private static final String SELECTED_INDEX_KEY = “SELECTED_INDEX_KEY”;



2. 接下来,重写onPause方法。获得Activity的私有Shared
Preference并得到它的Editor对象。



使用第1步中创建的键,存储实例的值,包括是否一个新的项目正在添加和任何在“new
item”输入框中的文本。



@Override

protected void onPause(){

super.onPause();



// Get the activity preferences object.

SharedPreferences uiState = getPreferences(0);



// Get the preferences editor.

SharedPreferences.Editor editor = uiState.edit();



// Add the UI state preference values.

editor.putString(TEXT_ENTRY_KEY, myEditText.getText().toString());

editor.putBoolean(ADDING_ITEM_KEY, addingNew);



// Commit the preferences.

editor.commit();

}



3. 编写一个restoreUIState方法,当程序重启时,应用在第2步中记录的实例的值。



修改onCreate方法,在最后部分添加对restoreUIState方法的调用。



@Override

public void onCreate(Bundle icicle) 

{

[ ... existing onCreate logic ... ]

restoreUIState();

}



private void restoreUIState() 

{

// Get the activity preferences object.

SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);



// Read the UI state values, specifying default values.

String text = settings.getString(TEXT_ENTRY_KEY, “”);

Boolean adding = settings.getBoolean(ADDING_ITEM_KEY, false);



// Restore the UI to the previous state.

if (adding) 

{

addNewItem();

myEditText.setText(text);

}

}



4. 使用onSaveInstanceState/onRestoreInstanceState机制来记录当前选择的项目的索引。它仅在非用户显式的指令杀死应用程序时保存和应用。



@Override

public void onSaveInstanceState(Bundle outState) 

{

outState.putInt(SELECTED_INDEX_KEY, myListView.getSelectedItemPosition());

super.onSaveInstanceState(outState);

}



@Override

public void onRestoreInstanceState(Bundle savedInstanceState) 

{

int pos = -1;

if (savedInstanceState != null)

if (savedInstanceState.containsKey(SELECTED_INDEX_KEY))

pos = savedInstanceState.getInt(SELECTED_INDEX_KEY, -1);

myListView.setSelection(pos);

}



当你运行To-Do List程序时,你应该看到了在会话期间UI状态的保存。但是,它还不能保存to-do列表的项目——你将在本章的后面添加这个核心的功能。

activity状态的保存和保持(onRetainNonConfigurationInstance和getLastNonConfigurationInstanc的更多相关文章

  1. activity状态的保存和恢复

    activity状态的保存和恢复 一.简介 1.保存activity状态 * 保存activity状态,onSaveInstanceState这个方法会自动保存有ID的组件的状态 * 没有ID的组件或 ...

  2. Activity 状态的保存和恢复

    Activity状态保存的两种情况 一.Activity状态保持概念 保存Activity的状态是非常重要的,例如我们在玩一个游戏的时候,突然来了一个电话,这个时候在接听完电话之后我们返回到游戏中,这 ...

  3. Android之Activity状态的保存和恢复

    系统在某些情况下会调用onSaveInstanceState()和onRestoreInstanceState() 这两个方法来保存和恢复Activity的状态. 一句话:Activity在" ...

  4. Android开发中Activity状态的保存与恢复

    当置于后台的Activity因内存紧张被系统自动回收的时候,再次启动它的话他会重新调用onCretae()从而丢失了之前置于后台前的状态. 这时候就要重写Activity的两个方法来保存和恢复状态,具 ...

  5. android activity状态的保存

    今天接到一个电面,途中面试官问到一个问题,如果一个activity在后台的时候,因为内存不足可能被杀死,在这之前如果想保存其中的状态数据,比如说客户填的一些信息之类的,该在哪个方法中进行. onSav ...

  6. 【Android 应用开发】Activity 状态保存 OnSaveInstanceState參数解析

    作者 : 韩曙亮 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38297083 一. 相关方法简单介绍 1. 状态保存方法演示 ...

  7. Android学习总结——Activity状态保存和恢复

    Android中启动一个Activity如果点击Home键该Activity是不会被销毁的,但是当进行某些操作时某些数据就会丢失,如下: Java class: package com.king.ac ...

  8. 【Android 应用开发】Activity 状态保存 OnSaveInstanceState参数解析

    作者 : 韩曙亮 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38297083 一. 相关方法简介 1. 状态保存方法示例 p ...

  9. Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信

    以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3364728.html 我前两天写过一篇博客<Android使用Fragment来 ...

随机推荐

  1. sql 语句中使用条件判断case then else end

    sql 语句中使用条件判断case then else end范例: SELECT les.[nLessonNo] FROM BS_Lesson AS les WHERE les.[sClassCod ...

  2. 解决json跨域时错误:SyntaxError: invalid label

    将数据做以下返回: $callback = $_GET['callback']; echo $callback.'('.json_encode(array('html'=>$html)).')' ...

  3. C/C++学习之基础-001

    1.C++虚函数的工作原理 虚函数(virtual function)需要虚函数表(virtual table)才能实现.如果一个类有函数声明成虚拟的,就会生成一个虚函数表,存放这个类的虚函数地址.若 ...

  4. 立体透视 perspective transform-style 倾斜旋转

    1.perspective 是设置镜头距离,距离越远视图越小,视图越近,视图越大.就像相机焦距一样.其只对子元素产生效果. 2.transform-style: preserve-3d 设置3d效果, ...

  5. 《JAVA学习笔记(1---13-4)》

    [1]问题: 1.什么叫做面向过程? 2.什么叫做面向对象? 解答: 1: 所谓的面向过程就是我们是一个执行者,我们要开发一个项目,这个项目要求要实现很多功能,作为执行者的我们就需要 去一个一个的找这 ...

  6. JS 基础事件的用法

    // 1.9以上用on // 案例一 // $('#btn').on('click', function(){ // //console.log(1); // alert('测试...'); // } ...

  7. C#基础--面向对象计算器

    static void Main(string[] args) { //new个对象 Calculator cal = new Calculator(); //做事情 cal.Run(); } /// ...

  8. 重拾java系列一java基础(4)

    本章主要回顾一些类的相关知识: (1)static: static 静态的: 属于类的资源, 使用类名访问.  静态属性: 只有一份的变量  静态方法: 是属于类方法, 可以使用类名直接访问. 静态方 ...

  9. 团队开发——冲刺1.a

    冲刺阶段一(第一天) 1.今天准备做什么? 在了解C#的基础上,深入熟悉Windows窗体应用程序,熟练掌握基本功能. 2.明天做什么:简单设计界面.

  10. 使用HackRF+GNU Radio 破解吉普车钥匙信号

    引文 我最近对软件定义的无线电技术(SDR)产生了浓厚的兴趣,而我对其中一款流行的SDR平台(HackRF)也产生了兴趣,而其频率接收的范围也在1MHz ~6GHz之间(范围较广).而这里也需要提及一 ...