activity中的onPause()和onSaveInstanceState()解析

转自: 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 改变字体大小后,焦点保留在原来位置不变,代码

 

[html]  view plain copy
 
  1. /**  
  2.  * Copyright (C) 2012 Togic Corporation. All rights reserved.  
  3.  *  
  4.  * Licensed under the Apache License, Version 2.0 (the "License");  
  5.  * you may not use this file except in compliance with the License.  
  6.  * You may obtain a copy of the License at  
  7.  *  
  8.  * http://www.apache.org/licenses/LICENSE-2.0  
  9.  *  
  10.  * Unless required by applicable law or agreed to in writing, software  
  11.  * distributed under the License is distributed on an "AS IS" BASIS,  
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  13.  * See the License for the specific language governing permissions and  
  14.  * limitations under the License.  
  15.  */  
  16.   
  17. package com.togic.settings.fragment;  
  18.   
  19. import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;  
  20. import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED;  
  21. import static android.provider.Settings.System.TEXT_SHOW_PASSWORD;  
  22.   
  23. import java.io.IOException;  
  24.   
  25. import android.app.Activity;  
  26. import android.app.ActivityManagerNative;  
  27. import android.app.Fragment;  
  28. import android.app.WallpaperManager;  
  29. import android.content.ContentResolver;  
  30. import android.content.Context;  
  31. import android.content.Intent;  
  32. import android.content.res.Configuration;  
  33. import android.graphics.Bitmap;  
  34. import android.graphics.drawable.Drawable;  
  35. import android.media.AudioManager;  
  36. import android.os.Bundle;  
  37. import android.os.Handler;  
  38. import android.os.Message;  
  39. import android.os.RemoteException;  
  40. import android.provider.Settings;  
  41. import android.view.LayoutInflater;  
  42. import android.view.View;  
  43. import android.view.ViewGroup;  
  44. import android.widget.ImageView;  
  45.   
  46. import com.togic.settings.App;  
  47. import com.togic.settings.R;  
  48. import com.togic.settings.util.LogUtil;  
  49. import com.togic.settings.view.MultiValueItem;  
  50. import com.togic.settings.view.OnValueChangeListener;  
  51. import com.togic.settings.view.ToggleItem;  
  52.   
  53. /**  
  54.  * @author [email protected] @date 2012-11-17  
  55.  */  
  56. public class DesktopSettings extends Fragment implements OnValueChangeListener {  
  57.   
  58.     private static final long DEFAULT_SCREEN_TIMEOUT = 300;  
  59.     private static final int DEFAULT_TOUCH_SOUND = 1;  
  60.     private static final int DEFAULT_PWD_VISIBLE = 1;  
  61.     private static final int NO_INTEM_FOCUS = 0;  
  62.   
  63.     private static final int TASK_DELAY = 2000;  
  64.   
  65.     private static final int GET_WALLPAPER = 0x0001;  
  66.     private static final int CHANGE_WALLPAPER = 0x0002;  
  67.     private static final String FOCUS_ITEM = "focusItem";  
  68.   
  69.     private Handler mTaskHandler = new Handler(App.sTaskRunner.getLooper()) {  
  70.         public void handleMessage(Message msg) {  
  71.             switch (msg.what) {  
  72.             case GET_WALLPAPER:  
  73.                 getWallpaper();  
  74.                 return;  
  75.             case CHANGE_WALLPAPER:  
  76.                 changeWallpaper(msg.arg1);  
  77.                 return;  
  78.             }  
  79.         }  
  80.     };  
  81.     private Handler mMainHandler = new Handler();  
  82.   
  83.     private Activity mActivity;  
  84.     private WallpaperManager mWpMgr;  
  85.     private ContentResolver mResolver;  
  86.     private Bitmap mSystemWp;  
  87.     private boolean mNeedSystemWallpaper = true;  
  88.     private AudioManager mAudioMgr;  
  89.   
  90.     private ImageView mPicture;  
  91.     private MultiValueItem mWallpaper;  
  92.     private MultiValueItem mFontSize;  
  93.     private MultiValueItem mSleep;  
  94.     private ToggleItem mTouchSound;  
  95.     private ToggleItem mPwdVisible;  
  96.     private int mFocusItem;  
  97.     private View view = null;  
  98.   
  99.     public void onAttach(Activity activity) {  
  100.         super.onAttach(activity);  
  101.         mActivity = activity;  
  102.         mResolver = activity.getContentResolver();  
  103.         mWpMgr = WallpaperManager.getInstance(activity);  
  104.     }  
  105.   
  106.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  107.             Bundle data) {  
  108.         view = inflater.inflate(R.layout.frag_desktop, null, false);  
  109.         initView(view);  
  110.         return view;  
  111.     }  
  112.   
  113. <span style="background-color: rgb(0, 204, 204);">    public void onActivityCreated(Bundle savedInstanceState) {  
  114.         if (savedInstanceState != null) {  
  115.             mFocusItem = savedInstanceState.getInt(FOCUS_ITEM);  
  116.         }  
  117.         super.onActivityCreated(savedInstanceState);  
  118.     }</span>  
  119.   
  120.     public void onDestroyView() {  
  121.         super.onDestroyView();  
  122.         recycle();  
  123.     }  
  124.   
  125.  <span style="background-color: rgb(0, 204, 204);">   public void onResume() {  
  126.         if (mFocusItem != NO_INTEM_FOCUS) {  
  127.             View v = (View) view.findViewById(mFocusItem);  
  128.             v.requestFocus();  
  129.         }</span>  
  130.         super.onResume();  
  131.     }  
  132.   
  133.     public void onDetach() {  
  134.         super.onDetach();  
  135.         System.gc();  
  136.     }  
  137. <span style="background-color: rgb(0, 204, 204);">  
  138.     public void onSaveInstanceState(Bundle outState) {  
  139.         mFocusItem = getFocusItem();  
  140.         if (mFocusItem != NO_INTEM_FOCUS) {  
  141.             outState.putInt(FOCUS_ITEM, mFocusItem);  
  142.         }  
  143.         super.onSaveInstanceState(outState);  
  144.     }  
  145.   
  146.     private int getFocusItem() {  
  147.         View v = view.findFocus();  
  148.         if (v == null) {  
  149.             return NO_INTEM_FOCUS;  
  150.         }  
  151.         if (mWallpaper.isMyChild(v)) {  
  152.             return R.id.desktop_wallpaper;  
  153.         } else if (mFontSize.isMyChild(v)) {  
  154.             return R.id.desktop_fontsize;  
  155.         } else if (mSleep.isMyChild(v)) {  
  156.             return R.id.desktop_sleep;  
  157.         } else if (mTouchSound.isMyChild(v)) {  
  158.             return R.id.desktop_sound;  
  159.         } else if (mPwdVisible.isMyChild(v)) {  
  160.             return R.id.desktop_password;  
  161.         }  
  162.         return NO_INTEM_FOCUS;  
  163.     }</span>  
  164.   
  165.     private void initView(View view) {  
  166.         mPicture = (ImageView) view.findViewById(R.id.desktop_picture);  
  167.         mWallpaper = (MultiValueItem) view.findViewById(R.id.desktop_wallpaper);  
  168.         mFontSize = (MultiValueItem) view.findViewById(R.id.desktop_fontsize);  
  169.         mSleep = (MultiValueItem) view.findViewById(R.id.desktop_sleep);  
  170.         mTouchSound = (ToggleItem) view.findViewById(R.id.desktop_sound);  
  171.         mPwdVisible = (ToggleItem) view.findViewById(R.id.desktop_password);  
  172.   
  173.         mTaskHandler.sendEmptyMessageDelayed(GET_WALLPAPER, 0);  
  174.   
  175.         final Configuration c = getResources().getConfiguration();  
  176.         mFontSize.setCurrentValue(String.valueOf(c.fontScale));  
  177.   
  178.         final long timeOut = Settings.System.getLong(mResolver,  
  179.                 SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_TIMEOUT);  
  180.         mSleep.setCurrentValue(Long.toString(timeOut));  
  181.   
  182.         final int touchSound = Settings.System.getInt(mResolver,  
  183.                 SOUND_EFFECTS_ENABLED, DEFAULT_TOUCH_SOUND);  
  184.         mTouchSound.setCurrentValue(touchSound != 0);  
  185.   
  186.         final int pwdVisible = Settings.System.getInt(mResolver,  
  187.                 TEXT_SHOW_PASSWORD, DEFAULT_PWD_VISIBLE);  
  188.         mPwdVisible.setCurrentValue(pwdVisible != 0);  
  189.   
  190.         mWallpaper.setOnValueChangeListener(this);  
  191.         mFontSize.setOnValueChangeListener(this);  
  192.         mSleep.setOnValueChangeListener(this);  
  193.         mTouchSound.setOnValueChangeListener(this);  
  194.         mPwdVisible.setOnValueChangeListener(this);  
  195.     }  
  196.   
  197.     private void recycle() {  
  198.         mNeedSystemWallpaper = false;  
  199.         if (mSystemWp != null) {  
  200.             mSystemWp.recycle();  
  201.             mSystemWp = null;  
  202.         }  
  203.     }  
  204.   
  205.     public void onValueChange(View parent, View child, String oldVal,  
  206.             String newVal) {  
  207.         if (parent == mWallpaper) {  
  208.             LogUtil.v("wallpaper changed: " + newVal);  
  209.             changeWallpaper(newVal);  
  210.         } else if (parent == mFontSize) {  
  211.             LogUtil.v("font size changed: " + newVal);  
  212.             changeFontSize(newVal);  
  213.         } else if (parent == mSleep) {  
  214.             LogUtil.v("sleep changed: " + newVal);  
  215.             changeScreenTimeout(newVal);  
  216.         } else if (parent == mTouchSound) {  
  217.             LogUtil.v("touch sound changed: " + newVal);  
  218.             changeTouchSound(newVal);  
  219.         } else if (parent == mPwdVisible) {  
  220.             LogUtil.v("password visible changed: " + newVal);  
  221.             changePwdVisible(newVal);  
  222.         }  
  223.     }  
  224.   
  225.     public void onConfigurationChanged(Configuration newConfig) {  
  226.         super.onConfigurationChanged(newConfig);  
  227.         LogUtil.v("********** new config: " + newConfig);  
  228.         mFontSize.setCurrentValue(String.valueOf(newConfig.fontScale));  
  229.     }  
  230.   
  231.     private void changeWallpaper(String newVal) {  
  232.         final int id = getWallpaperResourceId(newVal);  
  233.         mPicture.setImageResource(id);  
  234.         recycle();  
  235.   
  236.         mTaskHandler.removeMessages(CHANGE_WALLPAPER);  
  237.         final Message msg = mTaskHandler.obtainMessage(CHANGE_WALLPAPER, id, 0);  
  238.         mTaskHandler.sendMessageDelayed(msg, TASK_DELAY);  
  239.     }  
  240.   
  241.     private void changeFontSize(String fontSize) {  
  242.         try {  
  243.             changeFontSize(Float.parseFloat(fontSize));  
  244.         } catch (NumberFormatException e) {  
  245.             LogUtil.e("could not persist font size setting");  
  246.         }  
  247.     }  
  248.   
  249.     private void changeFontSize(final float f) {  
  250.         mTaskHandler.postDelayed(new Runnable() {  
  251.             public void run() {  
  252.                 try {  
  253.                     final Configuration c = getResources().getConfiguration();  
  254.                     c.fontScale = f;  
  255.                     ActivityManagerNative.getDefault()  
  256.                             .updatePersistentConfiguration(c);  
  257.                 } catch (RemoteException e) {  
  258.                     LogUtil.w("Can not save font size changed: " + f);  
  259.                 } catch (IllegalStateException e) {  
  260.                     LogUtil.w("Can not save font size changed: " + f);  
  261.                 }  
  262.             }  
  263.         }, 0);  
  264.     }  
  265.   
  266.     private void changeScreenTimeout(String timeOut) {  
  267.         try {  
  268.             changeScreenTimeout(Integer.parseInt(timeOut));  
  269.         } catch (NumberFormatException e) {  
  270.             LogUtil.e("could not persist screen timeout setting");  
  271.         }  
  272.     }  
  273.   
  274.     private void changeScreenTimeout(final int val) {  
  275.         mTaskHandler.postDelayed(new Runnable() {  
  276.             public void run() {  
  277.                 Settings.System.putLong(mResolver, SCREEN_OFF_TIMEOUT, val);  
  278.             }  
  279.         }, 0);  
  280.     }  
  281.   
  282.     private void changeTouchSound(String touchSound) {  
  283.         if (mAudioMgr == null) {  
  284.             mAudioMgr = (AudioManager) getActivity().getSystemService(  
  285.                     Context.AUDIO_SERVICE);  
  286.         }  
  287.   
  288.         if ("0".equals(touchSound)) {  
  289.             changeTouchSound(0);  
  290.         } else {  
  291.             changeTouchSound(1);  
  292.         }  
  293.     }  
  294.   
  295.     private void changeTouchSound(final int val) {  
  296.         mTaskHandler.postDelayed(new Runnable() {  
  297.             public void run() {  
  298.                 if (val == 0) {  
  299.                     mAudioMgr.unloadSoundEffects();  
  300.                 } else {  
  301.                     mAudioMgr.loadSoundEffects();  
  302.                 }  
  303.                 Settings.System.putInt(mResolver, SOUND_EFFECTS_ENABLED, val);  
  304.             }  
  305.         }, 0);  
  306.     }  
  307.   
  308.     private void changePwdVisible(String pwdVisible) {  
  309.         if ("0".equals(pwdVisible)) {  
  310.             changePwdVisible(0);  
  311.         } else {  
  312.             changePwdVisible(1);  
  313.         }  
  314.     }  
  315.   
  316.     private void changePwdVisible(final int val) {  
  317.         mTaskHandler.postDelayed(new Runnable() {  
  318.             public void run() {  
  319.                 Settings.System.putInt(mResolver, TEXT_SHOW_PASSWORD, val);  
  320.             }  
  321.         }, 0);  
  322.     }  
  323.   
  324.     private void getWallpaper() {  
  325.         final Bitmap src = mWpMgr.getBitmap();  
  326.         if (src == null) {  
  327.             return;  
  328.         }  
  329.   
  330.         // NOTE: scale src bitmap.  
  331.         final Bitmap b = Bitmap.createScaledBitmap(src, 150, 100, true);  
  332.         mMainHandler.postDelayed(new Runnable() {  
  333.             public void run() {  
  334.                 if (b == null) {  
  335.                     return;  
  336.                 } else if (mNeedSystemWallpaper) {  
  337.                     mSystemWp = b;  
  338.                     mPicture.setImageBitmap(b);  
  339.                 } else {  
  340.                     b.recycle();  
  341.                 }  
  342.   
  343.                 // FIXME: why can't recycle src bitmap immediately after  
  344.                 // create scaled bitmap.  
  345.                 // if (src != null) {  
  346.                 // src.recycle();  
  347.                 // }  
  348.                 System.gc();  
  349.             }  
  350.         }, 0);  
  351.     }  
  352.   
  353.     private int getWallpaperResourceId(String newVal) {  
  354.         if ("wallpaper_1".equals(newVal)) {  
  355.             return R.drawable.bg_main;  
  356.         } else {  
  357.             return R.drawable.bg_main2;  
  358.         }  
  359.     }  
  360.   
  361.     private void changeWallpaper(int id) {  
  362.         try {  
  363.             mWpMgr.setResource(id);  
  364.         } catch (IOException e) {  
  365.             e.printStackTrace();  
  366.         }  
  367.     }  
  368. }  

猜你喜欢

转载自chriszeng87.iteye.com/blog/2099836