Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android開發小知識點之Activity總結

android開發小知識點之Activity總結

編輯:關於Android編程

在做android項目開發時,就不得不遇到一個Activity的狀態組件,這個組件描述的是一個控件、一個窗體等的當前狀態信息。下面詳細介紹這個組件


一、Activity狀態

Activity有三種狀態:active/running、paused、stopped。

  1、active/running狀態,在當前屏幕時,即用戶可見的Activity,位於當前Task的棧頂。

  2、paused狀態,Activity失去焦點但對用戶依然可見。也就是說在它上面有另外一個非全屏或者透明的Activity,並成為了當前的焦點。它還沒有被其他的Activity完全遮蓋住,而paused的Activity依然是alive狀態的,它保留著所有的狀態和成員信息並連接至窗口管理器,但當系統處於極低內存的情況下,仍然可以殺死這個Activity。

  3、stopped 狀態,當Activity完全被另一個Activity覆蓋時,它仍然保留所有的狀態和成員信息。但它不再被用戶可見,所以它的窗口將被隱藏,當其它地方需要內存,則系統經常會殺死這個Activity。

  當Activity是paused或者stopped狀態時,系統可以通過要求它結束(調用它的finish()方法)或直接殺死它的進程來將它驅出內存。當它再次為用戶可見的時候,它只能完全重新啟動並恢復至以前的狀態。

啟動並恢復至以前的狀態。

二、為什麼會有這麼麻煩的狀態變化

  1、手機屏幕大小有限,只能看到有限的界面數量,用戶需要通過Back鍵或Home鍵或其他方式切換Activity。

  2、在有手機來電時,系統會優先切換顯示電話接聽界面。

  由於上述的一些原因,確實存在界面隨時可能發生切換的情況,最佳方式當然不是每次都直接銷毀之前的界面,很多時候我們也需要在回到之前界面後恢復之前的狀態。我們需要了解這些狀態,當然還包括要掌握Activity的“生命周期”等知識,這樣就能夠在Activity發生變化時,知其所以然,並能夠根據需求采取一定的措施,例如切換界面時,保存當前的界面信息,即使其被意外殺死也能恢復之前狀態。

三、Activity生命周期

\

當一個Activity從這個狀態轉變到另一個狀態時,它被以下列protected方法所通知:

public class Activity extends ApplicationContext 
{  
         protected void onCreate(Bundle savedInstanceState);
    
         protected void onStart();
    
         protected void onRestart(); 
    
         protected void onResume();
    
        protected void onPause();  
    
        protected void onStop();  
    
        protected void onDestroy();  
}

1、onCreate -- 當Activity第一次創建時會被調用(未被銷毀前不會被再次調用)。在這個方法中可以做一些初始化工作,例如對創建新的View、獲取並設置View的一些屬性、綁定列表的數據等等。如果能捕獲到Activity 狀態的話,這個方法傳遞進來的Bundle對象將存放了Activity當前的狀態。調用該方法後一般會調用onStart()方法。此時Activity不可見,所以並不是所有的初始化工作都適合在這裡做,例如一些動畫的開始。

  2、onRestart -- 在Activity被停止後重新啟動時會調用該方法。其後續會調用onStart方法。

  3、onStart -- 當Activity對於用戶可見前即調用這個方法。如果Activity回到前台則接著調用onResume() ,如果Activity隱藏則調用onStop()。此時Activity可能可見,但即使可見,也無法進行交互操作。

  4、onResume -- 在Activity開始與用戶交互前調用該方法。在這時該Activity 處於Activity 棧的頂部,並且接受用戶的輸入。其後續會調用 onPause() 方法。此時Activity也不一定可見,需要通過onWindowFocusChanged(boolean)來確定Activity是否可見。

  5、onPause -- 在系統開始准備恢復其它Activity時會調用該方法。這個方法中通常用來提交一些還沒保存的更改到持久數據中,停止一些動畫或其它一些耗CPU的操作等等。無論在該方法裡面進行任何操作,都需要較快速完成,因為如果它不返回的話,下一個Activity 將無法恢復出來。如果Activity 返回到前台將會調用onResume(),如果Activity變得對用戶不可見了將會調用onStop() 。

  6、onStop -- 在Activity對用戶不可見時將調用該方法。可能會因為當前Activity 正在被銷毀,或另一個Activity(已經存在的Activity 或新的Activity )已經恢復了正准備覆蓋它,而調用該方法。如果Activity 正准備返回與用戶交互時後續會調用onRestart ,如果Activity正在被釋放則會調用onDestroy 。

  7、onDestroy -- 在Activity被銷毀前會調用該方法。這是Activity能接收到的最後一個調用。可能會因為有人調用了finish方法使得當前Activity正在關閉,或系統為了保護內存臨時釋放這個Activity的實例,而調用該方法。你可以用isFinishing方法來區分這兩種不同的情況。

  要注意的是,onPause(),onStop(),onDestory()這3個方法都可能會因為系統內存不足而被系統直接kill。而平常從一個Activity轉向/回到另一個Activity時,當新Activity是full screen(彈出窗口,例如AlertDialog是不算的)的時候就會調用前一個Activity的onPause(),然後調用onStop(),而無論onPause或者onStop,都有可能被kill,所以一般在onPause時就應該保存需要持久化的一些數據(例如用戶編輯的信息)。

  onCreate、onStart、onResume都不是Activity准確能夠交互的點,真正的是onWindowFocusChaned()函數被執行時。

四、Android的進程

  android根據其重要性在內存不足的時候移去重要性最低的進程。重要性由高到低為:

  1、活動/前台進程

    指那些有組件正和用戶進行交互的應用程序進程。他們都是android嘗試通過回收資源來使其保持響應的進程。這些進程的數量非常少,只用到最後的關頭才會終止這些進

程。

    活動進程包括:

      處於“活動”狀態的Activity,也就是說,它們位於前台並對用戶事件進行響應。
      正在執行onReceive事件處理程序的廣播接收器。
      正在執行onCreate()、onStart()或onDestory事件處理程序的服務。
      正在運行,且已被標記為前台運行的服務。
  2、可見進程
    可見,但是非活動的進程是指那些駐留可見活動的進程。顧名思義,可見的活動能被用戶看到,但是他們並不是在前台運行或者能對用戶事件做出響應,比如,當一個活動Activity被部分遮擋的時候(被一個非全屏或者半透明狀態的Activity遮擋時)就會出現這類情況。這類進程的數量很少,只有在資源極度缺乏的環境下,為保證活動進程的繼續執行,才會終止這些進程。

  3、服務進程

    已經啟動的服務進程。服務支持在沒有可見界面的情況下,仍然能繼續不間斷地進行處理。因為後台服務沒有直接和用戶進行交互,所以它們的優先級要比可見進程低一些。但是他們仍然被認為是前台進程。除非活動或者可見進程需要資源,否則不會終止它們。

  4、後台進程
不可見,並且沒有任何正在運行的服務的活動的進程,通常會有大量的後台進程。這樣的程序擁有一個用戶不可見的Activity。這樣的程序在系統內存不足時,按照LRU的順序被結束。

    運行著一個對用戶不可見的Activity(調用過onStop() 方法)。這些進程對用戶體驗沒有直接的影響,可以在服務進程、可見進程、前台進程需要內存的時候回收。通常,系統中會有很多不可見進程在運行,他們被保存在LRU (least recently used) 列表中,以便內存不足的時候被第一時間回收。如果一個Activity正確的執行了它的生命周期,關閉這個進程對於用戶體驗沒有太大的影響。
  5、空進程
    這樣的進程不包含任何活動的程序部件。系統可能隨時關閉這類進程。未運行任何程序組件。運行這些進程的唯一原因是作為一個緩存,縮短下次程序需要重新使用的啟動時間。系統經常中止這些進程,這樣可以調節程序緩存和系統緩存的平衡。

  Android對進程的重要性評級的時候,選取它最高的級別。另外,當被另外的一個進程依賴的時候,某個進程的級別可能會增高。一個為其他進程服務的進程永遠不會比被服務的進程重要級低。因為服務進程比後台Activity進程重要級高,因此一個要進行耗時工作的Activity最好啟動一個Service來做這個工作,而不是開啟一個子進程――特別是這個操作需要的時間比Activity存在的時間還要長的時候。例如,在後台播放音樂,向網上上傳攝像頭拍到的圖片,使用Service可以使進程最少獲取到“服務進程”級別的重要級,而不用考慮Activity目前是什麼狀態。broadcast receivers做費時的工作的時候,也應該啟用一個服務而不是開一個線程。



五、Activity狀態的保存

protected void onSaveInstanceState (Bundle outState)
protected void onRestoreInstanceState (Bundle savedInstanceState)

onSaveInstanceState() 和 onRestoreInstanceState() 並不是生命周期方法。它們並不是總會被調用。例如通過Back造成的銷毀Activity時,它就不會被調用。應該只用它來為Activity保存一些臨時的狀態,而不能用來保存持久性的數據。而是應該用onPause()來達到這個目的。

  onPause()方法是在系統結束應用程序前調用的最後一個安全的方法。無法保證onStop和onDestroy會被調用,所以不能依賴這兩個方法來實現關鍵邏輯。

六、Activity的加載模式

  Activity加載模式(通過在AndroidManifest.xml文件中activity元素的android:launcherMode屬性設置) 。請參考文章結尾附帶的demo體驗Activity的加載模式。

  1、standard(默認)
    測試方式:MainActivity(standard),SecondActivity(standard)
    每次都是創建了新的Activity實例。

  2、singleTop
    測試方式:MainActivity(singTop),MainActivity自己intent自己
    測試方式:MainActivity(singleTop),SecondActivity(standard)
    和standard一樣是發送新的實例,但singleTop要求如果創建intent的時候棧頂已經有要創建的Activity實例,則將intent發送給該實例。例如給MainActivity設置singleTop,然後按鈕也是intent自己,那麼會發現一直都是MainActivity當前這個實例,因為他一直在棧頂,所以不會創建新的。

    如果用A打開B,而B再打開A,如此循環,如果A是設置了singleTop,B是默認,則每次A都是新的,因為每次要打開A時,棧頂都不是A,就要創建新的A實例(和都是 standard沒啥區別了)。
    此種模式的應用場景,目前想到就是為了解決自己在棧頂時,自己給自己發送intent可以不創建新的實例。實際中應用的也較少。

  3、singleTask
    測試方式:MainActivity(singleTask),SecondActivity(standard)
    只創建一個實例。如果發現有對應的Activity實例,則是此Activity實例之上的其他Activity實例全部出棧,使此Activity實例成為棧頂對象,顯示出來。
  4、singleInstance
    這個模式下的Activity單獨在一個task棧中。這個棧只有一個Activity。目的是為了多個Task共享一個Activity。

七、Activity與View的生命周期

  View和Activity一樣也有自己的生命周期,具體在View的周期中包含哪些通知函數,參見http://developer.android.com/reference/android/view/View.html。其中onMeasure、onLayout、onDraw最重要,而onMeasure最難理解(之後會單獨討論這個函數及其如何使用)。

八、Activity的注意事項

  1、onConfigurationChanged

    1)不設置Activity的android:conChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次。
    2)設置Activity的android:configChanges=”orientation”時,切屏還是會重新調用各個生命周期,切橫、豎屏時只會執行一次。
    3)設置Activity的android:configChanges=”orientation|keyboardHidden”時,切屏不會重新調用各個生命周期,只會執行重寫的onConfigurationChanged方法。

    在實際開發中,我們會因為生命周期的一些奇怪現象而接觸到這個函數。例如http://www.cnblogs.com/endure/p/3416736.html



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved