转自: http://blog.csdn.net/dashuxiaoai/article/details/8592330
当用户在开启一个新activity时,当前的activity可能在内存中处于停止状态也可能由于新activity需要更多内存而被系统杀掉了,但不论怎样,当用户在新activity上按返回键时,他希望看到的是原先的activity的界面。原先的activity如果是被重新创建,那么它要恢复到用户最后看到它的样子。那么我们怎么做呢?其实也不难,跟据上一节所述,在onPause()或onStop()或onDestyroy()中保存必要的数据就行了。但是现在google又冒出一个新的东西:onSaveInstanceState(),观其名可知其意:它是专门用来保存实例状态的,这个“实例”不是指的activity对象,而是它所在的进程,因为activity的销毁是因为它所在的进程被杀而造成的。onSaveInstanceState()是在系统感觉需要杀死activity时调用的,它被传入一个参数:Bundle,这个Bundle可以被认为是个map,字典之类的东西,用”键-值”来保存数据。
现在又叫人蛋疼了:不是可以在onPause()中保存数据吗?为什么又搞出这样一个家伙来?它们之间是省木关系呢?原来onSaveInstanceState()的主要目的是保存activity的状态有关的数据,当系统在杀死activity时,如果它希望activity下次出现的样子跟现在完全一样,那么它就调用这个onSaveInstanceState(),否则就不调用。所以要明白这一点:onSaveInstanceState()并不是永远都会调用。比如,当用户在一个activity上按返回时,就不会调用,因为用户此时明确知道这个activity是要被销毁的,并不期望下次它的样子跟现在一样(当然开发者可以使它保持临死时的表情,你非要这样做,系统也没办法),所以就不用调用onSaveInstanceState()。现在应该明白了:在onPause(),onStop()以及onDestroy()中需要保存的是那些需要永久化是数据,而不是保存用于恢复状态的数据,状态数据有专门的方法:onSaveInstanceState()。数据保存在一个Bundle中,Bundle被系统永久化。当再调用activity的onCreate()时,原先保存的bundle就被传入,以恢复上一次临死时的模样,如果上次死时没有保存Bundle,则为null。
还没完呢,如果你没有实现自己的onSaveInstanceState(),但是activity上控件的样子可能依然能被保存并恢复。原来activity类已实现了onSaveInstanceState(),在onSaveInstanceState()的默认实现中,会调用所有控件的相关方法,把控件们的状态都保存下来,比如EditText中输入的文字,CheckBox是否被选中等等。然而不是所有的控件都能被保存,这取决于你是否在layout文件中为控件赋了一个名字(android:id)。有名的就存,无名的不管。
既然有现成的可用,那么我们到底还要不要自己实现onSaveInstanceState()?这得看情况了,如果你自己的派生类中有变量影响到UI,或你程序的行为,当然就要把这个变量也保存了,那么就需要自己实现,否则就不需要,但大多数情况肯定需要自己实现一下下了。对了,别忘了在你的实现中调用父类的onSaveInstanceState()。
注:由于onSaveInstanceState()并不是每次销毁时都会调用,所以不要在其中保存那些需要永久化的数据,执行保存那些数据的最好地方是:onPause()中。
测试你程序的状态恢复能力的最好方法是:旋转屏幕,每当屏幕的方向改变时,当前的activity就会被系统销毁,然后重新创建(应该是进程被关闭!――不会吧?效率不高哦)。
事件检验真理
setttings 改变字体大小后,焦点保留在原来位置不变,代码
- /**
- * Copyright (C) 2012 Togic Corporation. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.togic.settings.fragment;
- import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
- import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED;
- import static android.provider.Settings.System.TEXT_SHOW_PASSWORD;
- import java.io.IOException;
- import android.app.Activity;
- import android.app.ActivityManagerNative;
- import android.app.Fragment;
- import android.app.WallpaperManager;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.res.Configuration;
- import android.graphics.Bitmap;
- import android.graphics.drawable.Drawable;
- import android.media.AudioManager;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.os.RemoteException;
- import android.provider.Settings;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ImageView;
- import com.togic.settings.App;
- import com.togic.settings.R;
- import com.togic.settings.util.LogUtil;
- import com.togic.settings.view.MultiValueItem;
- import com.togic.settings.view.OnValueChangeListener;
- import com.togic.settings.view.ToggleItem;
- /**
- * @author mountains.liu@togic.com @date 2012-11-17
- */
- public class DesktopSettings extends Fragment implements OnValueChangeListener {
- private static final long DEFAULT_SCREEN_TIMEOUT = 300;
- private static final int DEFAULT_TOUCH_SOUND = 1;
- private static final int DEFAULT_PWD_VISIBLE = 1;
- private static final int NO_INTEM_FOCUS = 0;
- private static final int TASK_DELAY = 2000;
- private static final int GET_WALLPAPER = 0x0001;
- private static final int CHANGE_WALLPAPER = 0x0002;
- private static final String FOCUS_ITEM = "focusItem";
- private Handler mTaskHandler = new Handler(App.sTaskRunner.getLooper()) {
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case GET_WALLPAPER:
- getWallpaper();
- return;
- case CHANGE_WALLPAPER:
- changeWallpaper(msg.arg1);
- return;
- }
- }
- };
- private Handler mMainHandler = new Handler();
- private Activity mActivity;
- private WallpaperManager mWpMgr;
- private ContentResolver mResolver;
- private Bitmap mSystemWp;
- private boolean mNeedSystemWallpaper = true;
- private AudioManager mAudioMgr;
- private ImageView mPicture;
- private MultiValueItem mWallpaper;
- private MultiValueItem mFontSize;
- private MultiValueItem mSleep;
- private ToggleItem mTouchSound;
- private ToggleItem mPwdVisible;
- private int mFocusItem;
- private View view = null;
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mActivity = activity;
- mResolver = activity.getContentResolver();
- mWpMgr = WallpaperManager.getInstance(activity);
- }
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle data) {
- view = inflater.inflate(R.layout.frag_desktop, null, false);
- initView(view);
- return view;
- }
- <span style="background-color: rgb(0, 204, 204);"> public void onActivityCreated(Bundle savedInstanceState) {
- if (savedInstanceState != null) {
- mFocusItem = savedInstanceState.getInt(FOCUS_ITEM);
- }
- super.onActivityCreated(savedInstanceState);
- }</span>
- public void onDestroyView() {
- super.onDestroyView();
- recycle();
- }
- <span style="background-color: rgb(0, 204, 204);"> public void onResume() {
- if (mFocusItem != NO_INTEM_FOCUS) {
- View v = (View) view.findViewById(mFocusItem);
- v.requestFocus();
- }</span>
- super.onResume();
- }
- public void onDetach() {
- super.onDetach();
- System.gc();
- }
- <span style="background-color: rgb(0, 204, 204);">
- public void onSaveInstanceState(Bundle outState) {
- mFocusItem = getFocusItem();
- if (mFocusItem != NO_INTEM_FOCUS) {
- outState.putInt(FOCUS_ITEM, mFocusItem);
- }
- super.onSaveInstanceState(outState);
- }
- private int getFocusItem() {
- View v = view.findFocus();
- if (v == null) {
- return NO_INTEM_FOCUS;
- }
- if (mWallpaper.isMyChild(v)) {
- return R.id.desktop_wallpaper;
- } else if (mFontSize.isMyChild(v)) {
- return R.id.desktop_fontsize;
- } else if (mSleep.isMyChild(v)) {
- return R.id.desktop_sleep;
- } else if (mTouchSound.isMyChild(v)) {
- return R.id.desktop_sound;
- } else if (mPwdVisible.isMyChild(v)) {
- return R.id.desktop_password;
- }
- return NO_INTEM_FOCUS;
- }</span>
- private void initView(View view) {
- mPicture = (ImageView) view.findViewById(R.id.desktop_picture);
- mWallpaper = (MultiValueItem) view.findViewById(R.id.desktop_wallpaper);
- mFontSize = (MultiValueItem) view.findViewById(R.id.desktop_fontsize);
- mSleep = (MultiValueItem) view.findViewById(R.id.desktop_sleep);
- mTouchSound = (ToggleItem) view.findViewById(R.id.desktop_sound);
- mPwdVisible = (ToggleItem) view.findViewById(R.id.desktop_password);
- mTaskHandler.sendEmptyMessageDelayed(GET_WALLPAPER, 0);
- final Configuration c = getResources().getConfiguration();
- mFontSize.setCurrentValue(String.valueOf(c.fontScale));
- final long timeOut = Settings.System.getLong(mResolver,
- SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_TIMEOUT);
- mSleep.setCurrentValue(Long.toString(timeOut));
- final int touchSound = Settings.System.getInt(mResolver,
- SOUND_EFFECTS_ENABLED, DEFAULT_TOUCH_SOUND);
- mTouchSound.setCurrentValue(touchSound != 0);
- final int pwdVisible = Settings.System.getInt(mResolver,
- TEXT_SHOW_PASSWORD, DEFAULT_PWD_VISIBLE);
- mPwdVisible.setCurrentValue(pwdVisible != 0);
- mWallpaper.setOnValueChangeListener(this);
- mFontSize.setOnValueChangeListener(this);
- mSleep.setOnValueChangeListener(this);
- mTouchSound.setOnValueChangeListener(this);
- mPwdVisible.setOnValueChangeListener(this);
- }
- private void recycle() {
- mNeedSystemWallpaper = false;
- if (mSystemWp != null) {
- mSystemWp.recycle();
- mSystemWp = null;
- }
- }
- public void onValueChange(View parent, View child, String oldVal,
- String newVal) {
- if (parent == mWallpaper) {
- LogUtil.v("wallpaper changed: " + newVal);
- changeWallpaper(newVal);
- } else if (parent == mFontSize) {
- LogUtil.v("font size changed: " + newVal);
- changeFontSize(newVal);
- } else if (parent == mSleep) {
- LogUtil.v("sleep changed: " + newVal);
- changeScreenTimeout(newVal);
- } else if (parent == mTouchSound) {
- LogUtil.v("touch sound changed: " + newVal);
- changeTouchSound(newVal);
- } else if (parent == mPwdVisible) {
- LogUtil.v("password visible changed: " + newVal);
- changePwdVisible(newVal);
- }
- }
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- LogUtil.v("********** new config: " + newConfig);
- mFontSize.setCurrentValue(String.valueOf(newConfig.fontScale));
- }
- private void changeWallpaper(String newVal) {
- final int id = getWallpaperResourceId(newVal);
- mPicture.setImageResource(id);
- recycle();
- mTaskHandler.removeMessages(CHANGE_WALLPAPER);
- final Message msg = mTaskHandler.obtainMessage(CHANGE_WALLPAPER, id, 0);
- mTaskHandler.sendMessageDelayed(msg, TASK_DELAY);
- }
- private void changeFontSize(String fontSize) {
- try {
- changeFontSize(Float.parseFloat(fontSize));
- } catch (NumberFormatException e) {
- LogUtil.e("could not persist font size setting");
- }
- }
- private void changeFontSize(final float f) {
- mTaskHandler.postDelayed(new Runnable() {
- public void run() {
- try {
- final Configuration c = getResources().getConfiguration();
- c.fontScale = f;
- ActivityManagerNative.getDefault()
- .updatePersistentConfiguration(c);
- } catch (RemoteException e) {
- LogUtil.w("Can not save font size changed: " + f);
- } catch (IllegalStateException e) {
- LogUtil.w("Can not save font size changed: " + f);
- }
- }
- }, 0);
- }
- private void changeScreenTimeout(String timeOut) {
- try {
- changeScreenTimeout(Integer.parseInt(timeOut));
- } catch (NumberFormatException e) {
- LogUtil.e("could not persist screen timeout setting");
- }
- }
- private void changeScreenTimeout(final int val) {
- mTaskHandler.postDelayed(new Runnable() {
- public void run() {
- Settings.System.putLong(mResolver, SCREEN_OFF_TIMEOUT, val);
- }
- }, 0);
- }
- private void changeTouchSound(String touchSound) {
- if (mAudioMgr == null) {
- mAudioMgr = (AudioManager) getActivity().getSystemService(
- Context.AUDIO_SERVICE);
- }
- if ("0".equals(touchSound)) {
- changeTouchSound(0);
- } else {
- changeTouchSound(1);
- }
- }
- private void changeTouchSound(final int val) {
- mTaskHandler.postDelayed(new Runnable() {
- public void run() {
- if (val == 0) {
- mAudioMgr.unloadSoundEffects();
- } else {
- mAudioMgr.loadSoundEffects();
- }
- Settings.System.putInt(mResolver, SOUND_EFFECTS_ENABLED, val);
- }
- }, 0);
- }
- private void changePwdVisible(String pwdVisible) {
- if ("0".equals(pwdVisible)) {
- changePwdVisible(0);
- } else {
- changePwdVisible(1);
- }
- }
- private void changePwdVisible(final int val) {
- mTaskHandler.postDelayed(new Runnable() {
- public void run() {
- Settings.System.putInt(mResolver, TEXT_SHOW_PASSWORD, val);
- }
- }, 0);
- }
- private void getWallpaper() {
- final Bitmap src = mWpMgr.getBitmap();
- if (src == null) {
- return;
- }
- // NOTE: scale src bitmap.
- final Bitmap b = Bitmap.createScaledBitmap(src, 150, 100, true);
- mMainHandler.postDelayed(new Runnable() {
- public void run() {
- if (b == null) {
- return;
- } else if (mNeedSystemWallpaper) {
- mSystemWp = b;
- mPicture.setImageBitmap(b);
- } else {
- b.recycle();
- }
- // FIXME: why can't recycle src bitmap immediately after
- // create scaled bitmap.
- // if (src != null) {
- // src.recycle();
- // }
- System.gc();
- }
- }, 0);
- }
- private int getWallpaperResourceId(String newVal) {
- if ("wallpaper_1".equals(newVal)) {
- return R.drawable.bg_main;
- } else {
- return R.drawable.bg_main2;
- }
- }
- private void changeWallpaper(int id) {
- try {
- mWpMgr.setResource(id);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
相关推荐
本文将详细解析从一个Activity(Activity1)跳转到另一个Activity(Activity2),然后再返回到原Activity(Activity1)时,这两个Activity分别会经历哪些生命周期方法。 #### Activity1的生命周期变化 1. **...
- 使用`Context.startActivity(Intent)`方法启动新Activity,Intent中包含要启动的目标Activity信息和可能的数据。 5. **Activity栈管理**: Android使用任务(Task)和回退栈(Back Stack)管理Activity。新启动的...
例如,我们可以在`onSaveInstanceState()`中保存Activity的状态,在`onRestoreInstanceState()`或`onCreate()`中恢复;在`onPause()`和`onStop()`中释放占用资源,避免内存泄漏。 在"Activity生命周期完美呈现"的...
onSaveInstanceState()和onRestoreInstanceState()是Activity生命周期中两个非常重要的方法。 onSaveInstanceState()会在以下情况被调用: * 从最近应用中选择运行其他的程序时。 * 当用户按下HOME键时。 * 屏幕...
此外,`Activity`的异常处理也是必须关注的,比如`onSaveInstanceState()`和`onRestoreInstanceState()`方法,用于在配置改变(如屏幕旋转)时保存和恢复`Activity`的状态。 总之,`Activity`是Android应用的核心...
开发者可以选择重写onSaveInstanceState()保存状态,并在onCreate()或onRestoreInstanceState()中恢复,或者通过配置文件声明不重启Activity。 7. **Task和Back Stack**:Task是Activity的集合,它们按照启动顺序...
3. 解析Intent:系统通过Intent中的信息找到对应的Activity组件。 4. 创建Activity:如果Activity不存在,系统会创建一个新的实例,调用onCreate(),然后调用onStart()和onResume()。 5. 显示Activity:如果Activity...
如多窗口模式、配置变化的处理(orientation change)、Activity的保存和恢复状态(onSaveInstanceState()和onRestoreInstanceState()),以及如何在Service或BroadcastReceiver中启动Activity。 除了以上内容,...
这篇博客文章可能详细解析了如何通过源码分析来理解和控制Activity的清理过程。通常,开发者会关注以下几个方面: 1. **内存管理**:避免在Activity中持有长时间运行的引用,这可能导致内存泄漏。使用WeakReference...
- 在`onSaveInstanceState()`中保存瞬态数据,以防Activity意外被销毁。 - 使用`onActivityResult()`处理启动其他Activity后的返回结果。 - 节约资源:在`onPause()`和`onStop()`中释放可复用资源,如内存缓存、...
- **onFreeze(Bundle outState)**:虽然这不是标准的生命周期方法,但它可能指的是`onSaveInstanceState(Bundle outState)`,用于在Activity被销毁前保存数据,以便于在Activity重建时恢复状态。 ```java @...
在Android开发过程中,理解应用程序如何启动及Activity的生命周期是非常重要的。这不仅有助于我们更好地管理程序的状态,还能帮助我们在遇到内存泄漏等问题时进行快速定位和解决。 #### ActivityThread `...
8. **Activity的可见性和状态**:在Activity的生命周期中,onPause()和onResume()方法用于处理Activity的暂停和恢复,onStop()则表示Activity完全不可见。理解这些状态对于处理如后台运行、屏幕旋转等事件至关重要。...
默认情况下,Android会销毁并重建Activity,但开发者可以重写onSaveInstanceState()和onRestoreInstanceState()来保存和恢复状态。 8. **多Activity交互**:如果应用包含多个Activity,测试它们之间的跳转逻辑和...
为了确保Activity在恢复时能正确显示之前的状态,开发者需要在`onSaveInstanceState(Bundle outState)`中保存关键数据,而在`onCreate(Bundle savedInstanceState)`或`onRestoreInstanceState(Bundle ...
【描述】:这篇博客文章并未提供具体的描述,但通过标题和标签,我们可以推测它可能深入解析了Android操作系统中的Activity组件。Activity是Android应用框架的关键部分,用于处理用户交互和屏幕显示。 【标签】:...
8. **Activity的保存与恢复状态**:在onSaveInstanceState(Bundle outState)中保存Activity的状态,如用户输入的数据,然后在onCreate(Bundle savedInstanceState)或onRestoreInstanceState(Bundle ...
- `onSaveInstanceState(Bundle outState)`:在`onPause()`之前可能被调用,用于保存当前Activity的状态,以防系统因资源紧张而销毁Activity,并在之后重建时恢复状态。 - `onDestroy()`:Activity被系统销毁时...
例如,合理使用`onSaveInstanceState()`和`onRestoreInstanceState()`可以保存和恢复用户的状态,即使Activity被销毁再重建。此外,了解`onActivityResult()`和`onNewIntent()`方法能帮助你处理返回结果和接收新的...
本文将深入解析Android Activity的生命週期,并通过详细说明每个阶段的功能与作用,帮助开发者更好地理解和控制Activity的状态变化。 ### Activity生命週期概述 Activity的生命週期是指从创建到销毁的一系列状态...