編輯:Android開發實例
上一節的內容是Android示例程序剖析之記事本的Android菜單部分,本節主要內容包括Activity的生命周期和自定義控件等。
Activity的生命周期
Activity類中有許多onXXX形式的函數可以重載,比如onCreate,onStart,onStop,onPause,那麼它們的調用順序到底是如何的呢?下面就通過一個實驗來進行分析。在做這個實驗之前,我們先得知道如何在Android中進行Log輸出的。我們要使用的是android.util.log類,這個類相當的簡單易用,因為它提供的全是一些靜態方法:
Log.v(String tag, String msg); //VERBOSE
Log.d(String tag, String msg); //DEBUG
Log.i(String tag, String msg); //INFO
Log.w(String tag, String msg); //WARN
Log.e(String tag, String msg); //ERROR
前面的tag是由我們定義的一個標識,一般可以用“類名_方法名“來定義。要在Eclipse中查看輸出的log信息,需要打開Logcat(Window->Show View->other->Android->LogCat即可打開)。
實驗一
我們要做的實驗非常簡單,就是有兩個Activity(我這裡分別叫做frmLogin和hello2),它們各自有一個button,可以從第一個跳到第二個,也可以從第二個跳回到第一個。配置文件AndroidManifest.xml非常簡單,第二個activity並沒有多余的信息需要指定。
XML/HTML代碼第一個activity的代碼如下:
Java代碼我在每個onXXX方法中都加入了log方法,值得注意的一點是按鈕單擊事件處理函數中,在最後我調用了finish();待會我會將此行注釋掉進行對比實驗。第二個activity的代碼和第一個完全一樣,只是將setClass的兩個參數反一下,這樣就可以簡單地實現在兩個Activity界面中來回切換的功能了。下面開始實驗,第一個實驗室從第一個activity跳到第二個activity(此時第一個關閉),然後從第二個跳回第一個(此時第二個關閉)。運行後觀察LogCat,得到如下畫面:
然後來進行第二個實驗,對代碼進行調整,我們把第一個activity中的finish()注釋掉,從第一個activity跳到第二個(此時第一個沒有關閉),然後第二個直接關閉(則第一個會重新來到前端),結果如圖所示,可以看出調用了FrmLogin的onRestart而不是onStart,因為第一個activity只是stop,而並沒有被destory掉。
前面兩個實驗都很好理解,可第三個實驗就讓我不明白了,過程如下:從第一個activity跳到第二個activity(此時第一個不關閉),然後第二個跳回第一個(此時第二個也不關閉),然後第一個再跳回第二個(此時第一個不關閉),照上面來推斷,應該還是會調用onRestart才對,可實際上它調用的卻是onStart,why???
這裡先不討論例子了,來看看官方文檔對Activity生命周期的介紹。
1. Android用Activity Stack來管理多個Activity,所以呢,同一時刻只會有最頂上的那個Activity是處於active或者running狀態。其它的Activity都被壓在下面了。
2. 如果非活動的Activity仍是可見的(即如果上面壓著的是一個非全屏的Activity或透明的Activity),它是處於paused狀態的。在系統內存不足的情況下,paused狀態的Activity是有可被系統殺掉的。只是不明白,如果它被干掉了,界面上的顯示又會變成什麼模樣?看來下回有必要研究一下這種情況了。
3. 幾個事件的配對可以比較清楚地理解它們的關系。Create與Destroy配成一對,叫entrie lifetime,在創建時分配資源,則在銷毀時釋放資源;往上一點還有Start與Stop一對,叫visible lifetime,表達的是可見與非可見這麼一個過程;最頂上的就是Resume和Pause這一對了,叫foreground lifetime,表達的了是否處於激活狀態的過程。
4. 因此,我們實現的Activity派生類,要重載兩個重要的方法:onCreate()進行初始化操作,onPause()保存當前操作的結果。除了Activity Lifecycle以外,Android還有一個Process Lifecycle的說明:
在內存不足的時候,Android是會主動清理門戶的,那它又是如何判斷哪個process是可以清掉的呢?文檔中也提到了它的重要性排序:
1. 最容易被清掉的是empty process,空進程是指那些沒有Activity與之綁定,也沒有任何應用程序組件(如Services或者IntentReceiver)與之綁定的進程,也就是說在這個process中沒有任何activity或者service之類的東西,它們僅僅是作為一個cache,在啟動新的Activity時可以提高速度。它們是會被優先清掉的。因此建議,我們的後台操作,最好是作成Service的形式,也就是說應該在Activity中啟動一個Service去執行這些操作。
2. 接下來就是background activity了,也就是被stop掉了那些activity所處的process,那些不可見的Activity被清掉的確是安全的,系統維持著一個LRU列表,多個處於background的activity都在這裡面,系統可以根據LRU列表判斷哪些activity是可以被清掉的,以及其中哪一個應該是最先被清掉。不過,文檔中提到在這個已被清掉的Activity又被重新創建的時候,它的onCreate會被調用,參數就是onFreeze時的那個Bundle。不過這裡有一點不明白的是,難道這個Activity被killed時,Android會幫它保留著這個Bundle嗎?
3. 然後就輪到service process了,這是一個與Service綁定的進程,由startService方法啟動。雖然它們不為用戶所見,但一般是在處理一些長時間的操作(例如MP3的播放),系統會保護它,除非真的沒有內存可用了。
4. 接著又輪到那些visible activity了,或者說visible process。前面也談到這個情況,被Paused的Activity也是有可能會被系統清掉,不過相對來說,它已經是處於一個比較安全的位置了。
5. 最安全應該就是那個foreground activity了,不到迫不得已它是不會被清掉的。這種process不僅包括resume之後的activity,也包括那些onReceiveIntent之後的IntentReceiver實例。在Android Application的生命周期的討論中,文檔也提到了一些需要注意的事項:因為Android應用程序的生存期並不是由應用本身直接控制的,而是由Android系統平台進行管理的,所以,對於我們開發者而言,需要了解不同的組件Activity、Service和IntentReceiver的生命,切記的是:如果組件的選擇不當,很有可能系統會殺掉一個正在進行重要工作的進程。
自定義控件
這裡主要介紹下“編輯日志”中使用的一個自定義EditText控件,它的效果如下圖:
主要功能就是在文本語句之間繪制分割線。
Java代碼主要工作就是重載onDraw方法,利用從TextView繼承下來的getLineCount函數獲取文本所占的行數,以及getLineBounds來獲取特定行的基准高度值,而且這個函數第二個參數會返回此行的“外包裝”值。再利用這些值繪制這一行的線條。為了讓界面的View使用自定義的EditText類,必須在配置文件中進行設置。
XML/HTML代碼這裡class="com.example.android.notepad.NoteEditor$LinedEditText"就指明了應當使用自定義的LinedEditText類。
為了引入這個概率 首先從需求說起 即:現有某Activity專門用於手機屬性設置 那麼應該如何做呢? 根據已學知識 很快一個念頭閃過 即:Activity + P
本文實例講述了Android實現多線程下載文件的方法。分享給大家供大家參考。具體如下: 多線程下載大概思路就是通過Range 屬性實現文件分段,然後用Random
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我