在这篇文章中,我们将带领您了解片段中未调用onSaveInstanceState的全貌,包括未调用的段,对于覆盖进程忽略的相关情况。同时,我们还将为您介绍有关Activity的onSaveInstan
在这篇文章中,我们将带领您了解片段中未调用onSaveInstanceState的全貌,包括未调用的段,对于覆盖进程忽略的相关情况。同时,我们还将为您介绍有关Activity的onSaveInstanceState()和 onRestoreInstanceState()方法、android onSaveInstanceState、android onSaveInstanceState 相关、Android onSaveInstanceState和onRestoreInstanceState触发的时机的知识,以帮助您更好地理解这个主题。
本文目录一览:- 片段中未调用onSaveInstanceState(未调用的段,对于覆盖进程忽略)
- Activity的onSaveInstanceState()和 onRestoreInstanceState()方法
- android onSaveInstanceState
- android onSaveInstanceState 相关
- Android onSaveInstanceState和onRestoreInstanceState触发的时机
片段中未调用onSaveInstanceState(未调用的段,对于覆盖进程忽略)
我知道有人问过这个问题,但是我遵循了所有答案,但仍然有同样的问题。我有两个脚本,一个是片段管理器(IngredientsActivity),另一个是片段(OtherList)。代码如下
成分活动
import java.util.ArrayList;import android.app.ActionBar;import android.app.FragmentTransaction;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.view.Gravity;import android.view.LayoutInflater;import android.view.Menu;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;public class IngredientsActivity extends FragmentActivity implements ActionBar.TabListener { private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.check_list); // Set up the action bar. final ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // For each of the sections in the app, add a tab to the action bar. actionBar.addTab(actionBar.newTab().setText("Alcahol").setTabListener(this)); actionBar.addTab(actionBar.newTab().setText("Juice").setTabListener(this)); actionBar.addTab(actionBar.newTab().setText("Other").setTabListener(this)); } @Override public void onRestoreInstanceState(Bundle savedInstanceState) { if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) { getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM)); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); //OVERRIDE SAVE ON MAINCLASS outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex()); } @Override public boolean onCreateOptionsMenu(Menu menu) { return true; } @Override public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { } @Override public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { if (tab.getPosition() == 0) { AlcoholList simpleListFragment = new AlcoholList(); getSupportFragmentManager().beginTransaction().replace(R.id.containert, simpleListFragment).commit(); } else if (tab.getPosition() == 1) { JuiceList androidlidt = new JuiceList(); getSupportFragmentManager().beginTransaction().replace(R.id.containert, androidlidt).commit(); } else { OtherList androidversionlist = new OtherList(); getSupportFragmentManager().beginTransaction().replace(R.id.containert, androidversionlist).commit(); } } @Override public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { } public static class DummySectionFragment extends Fragment { public DummySectionFragment() { } public static final String ARG_SECTION_NUMBER = "section_number"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView textView = new TextView(getActivity()); textView.setGravity(Gravity.CENTER); Bundle args = getArguments(); textView.setText(Integer.toString(args.getInt(ARG_SECTION_NUMBER))); return textView; } }}
其他清单
import java.util.ArrayList;import android.content.Context;import android.os.Bundle;import android.support.v4.app.ListFragment;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.CheckBox;import android.widget.ListView;public class OtherList extends ListFragment{ MyCustomAdapter dataAdapter = null; private ArrayList<String> recipesList;private ArrayList<Items> stateList ;public OtherList() { setRetainInstance(true); stateList = new ArrayList<Items>(); Items _states1 = new Items ("Gin",false); stateList.add(_states1);Items _states2 = new Items ("Ginger Liqueur",false); stateList.add(_states2);Items _states3 = new Items ("Citrus Vodka",false); stateList.add(_states3);Items _states4 = new Items ("Champagne",false); stateList.add(_states4);Items _states5 = new Items ("Coconut Rum",false); stateList.add(_states5);Items _states6 = new Items ("Pear Vodka",false); stateList.add(_states6);Items _states7 = new Items ("Rum",false); stateList.add(_states7);Items _states8 = new Items ("Tequila",false); stateList.add(_states8);Items _states9 = new Items ("Triple Sec",false); stateList.add(_states9);Items _states10 = new Items ("Kahlua",false); stateList.add(_states10); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); dataAdapter = new MyCustomAdapter(this.getActivity(),R.layout.da_item, stateList); setListAdapter(dataAdapter); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.list_fragment, container, false); } @Override public void onListItemClick(ListView list, View v, int position, long id) { } private class MyCustomAdapter extends ArrayAdapter<Items>{ private ArrayList<Items> stateList;public MyCustomAdapter(Context context, int textViewResourceId,ArrayList<Items> stateList) { super(context, textViewResourceId, stateList); this.stateList = new ArrayList<Items>(); this.stateList.addAll(stateList);} private class ViewHolder { CheckBox name; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; Log.v("ConvertView", String.valueOf(position)); if (convertView == null) { LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.da_item, null); holder = new ViewHolder(); holder.name = (CheckBox) convertView.findViewById(R.id.ingredientbox); convertView.setTag(holder); holder.name.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { CheckBox cb = (CheckBox) v; Items _state = (Items) cb.getTag(); _state.setSelected(cb.isChecked()); } }); } else { holder = (ViewHolder) convertView.getTag(); } Items state = stateList.get(position); holder.name.setText(state.getName()); holder.name.setChecked(state.isSelected()); holder.name.setTag(state); return convertView; }}@Overridepublic void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState);} @Override public void onSaveInstanceState(Bundle outState) { Log.d("hey","SAVING"); //NOT SAVING super.onSaveInstanceState(outState); save(); outState.putStringArrayList("index", recipesList); } } } } }
我发现有多个建议可以覆盖onSaveInstanceState的建议,并且我发现更多建议告诉我使用setRetainInstance。我不知道如果要保存列表的值,为什么setRetainInstance状态会有所帮助。
我的问题-为什么要在List View中保存值,为什么不调用OtherList类中的save或有什么更好的方法实现
(在这种情况下,我使用的是复选框)
答案1
小编典典onSaveInstanceState()
仅在Android系统可能需要重新创建该Fragment的特定实例时才调用。有许多实例远离片段导航,甚至破坏不被调用的片段。请查阅文档以获取更多信息,请也阅读该Activity.onSaveInstanceState()
文档,因为这也适用于此:http:
//developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)
http:
//developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
编辑:在您的情况下,您每次用户导航回到该片段时,您都不能重新创建该片段。我建议考虑使用ViewPager和FragmentPagerAdapter自动管理片段。另外请看这篇文章:ViewPager和fragments
—存储fragment状态的正确方法是什么?
Activity的onSaveInstanceState()和 onRestoreInstanceState()方法
@Override
protected void onRestoreInstanceState(Bundle savedState) {
super.onRestoreInstanceState(savedState);
mSeries = (CategorySeries) savedState.getSerializable("current_series");
mRenderer = (DefaultRenderer) savedState.getSerializable("current_renderer");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("current_series", mSeries);
outState.putSerializable("current_renderer", mRenderer);
}
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,
它们不同于onCreate()、onPause()等生命周期方法,它们并不一定会被触发。
当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,
onSaveInstanceState() 会被调用(由运行状态进入暂停状态或停止状态)。
但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。
因为在这种情况下,用户的行为决定了不需要保存Activity的状态。
通常onSaveInstanceState()只适合用于保存一些临时性的状态,
而onPause()适合用于数据的持久化保存。
另外,当屏幕的方向发生了改变, Activity会被摧毁并且被重新创建,
如果你想在Activity被摧毁前缓存一些数据,并且在Activity被重新创建后恢复缓存的数据。
android onSaveInstanceState
无意中留意到 onCreate(Bundle savedInstanceState) ,savedInstanceState究竟是什么,于是上网搜了搜
当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。
注意上面的双引号,何为“容易”?言下之意就是该activity还没有被销毁,而仅仅是一种可能性。这种可能性有哪些?通过重写一个 activity的所有生命周期的onXXX方法,包括onSaveInstanceState和onRestoreInstanceState方法,我 们可以清楚地知道当某个activity(假定为activity A)显示在当前task的最上层时,其onSaveInstanceState方法会在什么时候被执行,有这么几种情况:
1、当用户按下HOME键时。
这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则
2、长按HOME键,选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从activity A中启动一个新的activity时。
5、屏幕方向切换时,例如从竖屏切换到横屏时。
在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行。
总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。
至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState 方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提 是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行。
另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原。
转载于: http://gundumw100.iteye.com/blog/1115080
例子:
Activity里的onSaveInstanceState()方法,虽然系统会自动调用它来保存Activity的一些数据,但当除它默认要保存的数据外,我们还要保存一些其他数据的时候, 我们就需要覆盖onSaveInstanceState()方法来保存Activity的附件信息。例如在播放视频过程中,横竖屏切换要保持当前播放时间进度,在默认情况下播放时间是不被自动保存的。
写了一个简单的播放视频的例子,在横竖屏切换时保持当前播放进度,效果图:
横屏切换:
mian.xml的代码:
[html] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<VideoView android:id="@+id/myvideo" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MainAcrtivity主要代码部分:
[java] view plaincopy
private VideoView videoView;
private static final String VIDEO_PATH = Environment
.getExternalStorageDirectory()
+ File.separator
+ "mymovie"
+ File.separator + "shenghuaweiji.mp4";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.v("tag", "onCreate");
if (videoView == null) {
videoView = (VideoView) this.findViewById(R.id.myvideo);
MediaController controller = new MediaController(this);
videoView.setMediaController(controller);
videoView.setVideoPath(VIDEO_PATH);
videoView.requestFocus();
}
if (savedInstanceState != null
&& savedInstanceState.getInt("currentposition") != 0) {
videoView.seekTo(savedInstanceState.getInt("currentposition"));
}
videoView.start();
}
onCreate方法中的参数savedInstanceState就是保存的Activity一些状态。
[java] view plaincopy
savedInstanceState.getInt("currentposition")
获取视频播放时间。
实现并覆盖了onSaveInstanceState方法:
[java] view plaincopy
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
outState.putInt("currentposition", videoView.getCurrentPosition());
Log.v("tag", "onSaveInstanceState");
super.onSaveInstanceState(outState);
}
红色代码是将当前video的播放时间存储在Bundle中。
这样在横竖屏切换时保证了播放状态,源代码:http://bigcateasymorse.googlecode.com/svn/trunk/save-activity-state1.0/
android onSaveInstanceState 相关
今天用到了 onSaveInstanceState 相关的函数,感觉理解的还是不够深刻,记录一下
在 activity 被杀掉之前调用保存每个实例的状态,以保证该状态可以在 onCreate (Bundle) 或者 onRestoreInstanceState (Bundle) (传入的 Bundle 参数是由 onSaveInstanceState 封装好的) 中恢复。这个方法在一个 activity 被杀死前调用,当该 activity 在将来某个时刻回来时可以恢复其先前状态。例如,如果 activity B 启用后位于 activity A 的前端,在某个时刻 activity A 因为系统回收资源的问题要被杀掉,A 通过 onSaveInstanceState 将有机会保存其用户界面状态,使得将来用户返回到 activity A 时能通过 onCreate (Bundle) 或者 onRestoreInstanceState (Bundle) 恢复界面的状态。
不要将这个方法和 activity 生命周期回调如 onPause () 或 onStop () 搞混淆了,onPause () 在 activtiy 被放置到背景或者自行销毁时总会被调用,onStop () 在 activity 被销毁时被调用。一个会调用 onPause () 和 onStop (),但不触发 onSaveInstanceState 的例子是当用户从 activity B 返回到 activity A 时:没有必要调用 B 的 onSaveInstanceState (Bundle),此时的 B 实例永远不会被恢复,因此系统会避免调用它。一个调用 onPause () 但不调用 onSaveInstanceState 的例子是当 activity B 启动并处在 activity A 的前端:如果在 B 的整个生命周期里 A 的用户界面状态都没有被破坏的话,系统是不会调用 activity A 的 onSaveInstanceState (Bundle) 的。
默认的实现负责了大部分 UI 实例状态 (的保存),采用的方式是调用 UI 层上每个拥有 id 的 view 的 onSaveInstanceState () ,并且保存当前获得焦点的 view 的 id (所有保存的状态信息都会在默认的 onRestoreInstanceState (Bundle) 实现中恢复)。如果你覆写这个方法来保存额外的没有被各个 view 保存的信息,你可能想要在默认实现过程中调用或者自己保存每个视图的所有状态。如果被调用,这个方法会在 onStop () 前被触发,但系统并不保证是否在 onPause () 之前或者之后触发。
点击返回键,或 finish,当前 activity 是不会调用 onSaveInstanceState 方法的
说一下返回情况,一般在 onSaveInstanceState 存储的值,可以在两个地方得到:
- onCreate(Bundle savedInstanceState)
- onRestoreInstanceState(Bundle savedInstanceState)
onCreate 这个函数,我们继承它的时候,经常不会说把 super 这行代码去掉,因为前面它有很多代码都是包含了如何用 savedInstanceState 信息来还原界面的。
onRestoreInstanceState 这个函数的调用是在 onStart 到 onResume 之间执行的。
为什么要有两个来调用?我觉得这跟 Activity 保存和还原的方式有关。举个例子来说,如果我们调用了 startActivity 从 Activity A 跳转到了 Activity B,那么 Activity A 只调用到了 onStop,它本身并没有被消除,只是存到了 stack 中去了。当你在 Activity B 中点了 Back 键,回到 Activity A 中来,这个时候 Activity A 是从 onStart 开始调用的。所以很明显,onCreate 这里,我们没有经过,不能在这里读到保存的信息,但是有了 onRestoreInstanceState,我们又可以做到了。
说说 onSaveInstanceState 的缺点,我们可以看到,只有在 onCreate 和 onRestoreInstanceState 这样非常不灵活,而且只能用 Bundle 这个也限制了我们的代码编写。所以 Android 还提供了一个 API:onRetainNonConfigurationInstance
onRetainNonConfigurationInstance 的返回值是一个 object,所以在这里可以把 integer, string 这些对象和一些自定义对象,返回出去,不用再受到 bundle 的局限。
onRetainNonConfigurationInstance 的返回值是通过 getLastNonConfigurationInstance 调用的。可以通过
- Object obj = getLastNonConfigurationInstance();
或 cast 来转换对象如下例所示:
- String str = (String) getLastNonConfigurationInstance();
Android onSaveInstanceState和onRestoreInstanceState触发的时机
先看Application Fundamentals上的一段话:
Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key)
从这句话可以知道,当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。
注意上面的双引号,何为“容易”?言下之意就是该activity还没有被销毁,而仅仅是一种可能性。这种可能性有哪些?通过重写一个 activity的所有生命周期的onXXX方法,包括onSaveInstanceState和onRestoreInstanceState方法,我们可以清楚地知道当某个activity(假定为activity A)显示在当前task的最上层时,其onSaveInstanceState方法会在什么时候被执行,有这么几种情况:
1、当用户按下HOME键时。
这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则
2、长按HOME键,选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从activity A中启动一个新的activity时。
5、屏幕方向切换时,例如从竖屏切换到横屏时。
在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行
总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则 onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。
至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和 onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行
另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原
文章出处:http://qq361119908.iteye.com/blog/813282
关于片段中未调用onSaveInstanceState和未调用的段,对于覆盖进程忽略的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Activity的onSaveInstanceState()和 onRestoreInstanceState()方法、android onSaveInstanceState、android onSaveInstanceState 相关、Android onSaveInstanceState和onRestoreInstanceState触发的时机等相关知识的信息别忘了在本站进行查找喔。
本文标签: