Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android四大組件之Activity

Android四大組件之Activity

編輯:關於android開發

Android四大組件之Activity


做Android開發的沒有不知道Activity的,Activity是開發者遇到最頻繁, 最多的組件。這裡把一些比較不經常用到的知識做一個匯總。

Activity生命周期

這裡寫圖片描述

引用塊內容

要點

onStart(), onResume()為可見狀態; onPause(),為部分可見狀態; 其他為不可見狀態 onSaveInstanceState 保存狀態; onRestoreInstanceState恢復狀態

Activity 啟動模式

Activity啟動方式有四種,分別是:

standard singleTop singleTask singleInstance

standard:默認模式,可以不用寫配置。在這個模式下,都會默認創建一個新的實例。因此,在這種模式下,可以有多個相同的實例,也允許多個相同Activity疊加。

singleTop: 可以有多個實例,但是不允許多個相同Activity疊加。即,如果Activity在棧頂的時候,啟動相同的Activity,不會創建新的實例,而會調用其onNewIntent方法。

例如:若我有兩個Activity名為B1,B2,兩個Activity內容功能完全相同,都有兩個按鈕可以跳到B1或者B2,唯一不同的是B1為standard,B2為singleTop。
若我意圖打開的順序為B1->B2->B2,則實際打開的順序為B1->B2(後一次意圖打開B2,實際只調用了前一個的onNewIntent方法)
若我意圖打開的順序為B1->B2->B1->B2,則實際打開的順序與意圖的一致,為B1->B2->B1->B2。

singleTask: 只有一個實例。在同一個應用程序中啟動他的時候,若Activity不存在,則會在當前task創建一個新的實例,若存在,則會把task中在其之上的其它Activity destory掉並調用它的onNewIntent方法。如果是在別的應用程序中啟動它,則會新建一個task,並在該task中啟動這個Activity,singleTask允許別的Activity與其在一個task中共存,也就是說,如果我在這個singleTask的實例中再打開新的Activity,這個新的Activity還是會在singleTask的實例的task中。

例如:
若我的應用程序中有三個Activity,C1,C2,C3,三個Activity可互相啟動,其中C2為singleTask模式,那麼,無論我在這個程序中如何點擊啟動,如:C1->C2->C3->C2->C3->C1-C2,C1,C3可能存在多個實例,但是C2只會存在一個,並且這三個Activity都在同一個task裡面。
但是C1->C2->C3->C2->C3->C1-C2,這樣的操作過程實際應該是如下這樣的,因為singleTask會把task中在其之上的其它Activity destory掉。
操作:C1->C2 C1->C2->C3 C1->C2->C3->C2 C1->C2->C3->C2->C3->C1 C1->C2->C3->C2->C3->C1-C2
實際:C1->C2 C1->C2->C3 C1->C2 C1->C2->C3->C1 C1->C2

若是別的應用程序打開C2,則會新啟一個task。
如別的應用Other中有一個activity,taskId為200,從它打開C2,則C2的taskIdI不會為200,例如C2的taskId為201,那麼再從C2打開C1、C3,則C2、C3的taskId仍為201。
注意:如果此時你點擊home,然後再打開Other,發現這時顯示的肯定會是Other應用中的內容,而不會是我們應用中的C1 C2 C3中的其中一個。

singleInstance: 只有一個實例,並且這個實例獨立運行在一個task中,這個task只有這個實例,不允許有別的Activity存在。

例如:
程序有三個ActivityD1,D2,D3,三個Activity可互相啟動,其中D2為singleInstance模式。那麼程序從D1開始運行,假設D1的taskId為200,那麼從D1啟動D2時,D2會新啟動一個task,即D2與D1不在一個task中運行。假設D2的taskId為201,再從D2啟動D3時,D3的taskId為200,也就是說它被壓到了D1啟動的任務棧中。

若是在別的應用程序打開D2,假設Other的taskId為200,打開D2,D2會新建一個task運行,假設它的taskId為201,那麼如果這時再從D2啟動D1或者D3,則又會再創建一個task,因此,若操作步驟為other->D2->D1,這過程就涉及到了3個task了。

Activity傳遞參數

Intent 傳遞參數類型:
boolean, char, byte, double,float,int, long, short 基本數據類型及其數組
CharSequence/CharSequence[], String/String[], Bundle
以及實現了 SerializableParcelable 的對象

Serializable: java提供, 所有實現了Serializable的類,都是可序列化類。不需要實現任何方法。
Parcelable:android 特有,效率較高。需要重寫 writeToParcel()

選擇序列化方法的原則

在使用內存的時候,ParcelableSerializable 性能高,所以推薦使用 Parcelable

Serializable 在序列化的時候會產生大量的臨時變量,從而引起頻繁的GC。

Parcelable 不能使用在要將數據存儲在磁盤上的情況,因為 Parcelable 不能很好的保證數據的持續性在外界有變化的情況下。盡管 Serializable 效率低點,但此時還是建議使用 Serializable

實現Parcelable步驟

implements Parcelable

重寫writeToParcel方法,將你的對象序列化為一個Parcel對象,即:將類的數據寫入外部提供的Parcel中,打包需要傳遞的數據到Parcel容器保存,以便從 Parcel容器獲取數據

重寫describeContents方法,內容接口描述,默認返回0就可以

實例化靜態內部對象CREATOR實現接口Parcelable.Creator

例如:

public class MyDemo implements Parcelable {
    private int mData;
    private int mHaha;

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
        out.writeInt(mHaha);
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public MyDemo createFromParcel(Parcel in) {
            return new MyDemo(in);
        }

        public MyDemo[] newArray(int size) {
            return new MyDemo[size];
        }
    };

    private MyDemo(Parcel in) {
        mData = in.readInt();
        mHaha = in.readInt();
    }
}

Acivity configChanges屬性

一般在AndroidManifest.xml文件中都沒有使用到 android:configChanges =”orientation|screenSize”配置,當然還是很有用的。
就是如果配置了這個屬性,當我們橫豎屏切換的時候會直接調用onCreate方法中的 onConfigurationChanged 方法,而不會重新執行onCreate方法,那當然如果不配置這個屬性的話就會重新調用onCreate方法了

android:configChanges=[“mcc“, “mnc“, “locale“,
touchscreen“, “keyboard“, “keyboardHidden“,
navigation“, “screenLayout“, “fontScale“, “uiMode“,
orientation“, “screenSize“, “smallestScreenSize“]

mcc: The IMSI mobile country code (MCC) has changed — a SIM has been detected and updated the MCC.
IMSI(國際移動用戶識別碼)發生改變,檢測到SIM卡,或者更新MCC mnc: The IMSI mobile network code (MNC) has changed — a SIM has been detected and updated the MNC.
IMSI網絡發生改變,檢測到SIM卡,或者更新MCC
其中mcc和mnc理論上不可能發生變化 locale: The locale has changed — the user has selected a new language that text should be displayed in.
語言發生改變,用戶選擇了一個新的語言,文字應該重新顯示 touchscreen: The touchscreen has changed. (This should never normally happen.)
觸摸屏發生改變,這通常是不應該發生的 keyboard: The keyboard type has changed — for example, the user has plugged in an external keyboard.
鍵盤類型發生改變,例如,用戶使用了外部鍵盤 **keyboardHidden:**The keyboard accessibility has changed — for example, the user has revealed the hardware keyboard.
鍵盤發生改變,例如,用戶使用了硬件鍵盤
navigation: The navigation type (trackball/dpad) has changed. (This should never normally happen.)
導航發生改變,(這通常不應該發生) 舉例:連接藍牙鍵盤,連接後確實導致了navigation的類型發生變化。因為連接藍牙鍵盤後,我可以使用方向鍵來navigate了 screenLayout: The screen layout has changed — this might be caused by a different display being activated.
屏幕的布局發生改變,這可能導致激活不同的顯示 fontScale: The font scaling factor has changed — the user has selected a new global font size.
全局字體大小縮放發生改變 orientation: The screen orientation has changed — that is, the user has rotated the device.設備旋轉,橫向顯示和豎向顯示模式切換。 screenSize: 屏幕大小改變了 smallestScreenSize: 屏幕的物理大小改變了,如:連接到一個外部的屏幕上 layoutDirection屬性(),當改變語言設置後,該屬性也會成newConfig中的一個mask位。所以ActivityManagerService(實際在ActivityStack)在決定是否重啟Activity的時候總是判斷為重啟。
需要在android:configChanges 中同時添加locale和layoutDirection。
在不退出應用的情況下切換到Settings裡切換語言,發現該Activity還是重啟了。

Activity windowSoftInputMode

windowSoftInputMode 是來設置窗口軟鍵盤的交互模式, 屬性一共有9個取值:

stateUnspecifiedstateUnchangedstateHiddenstateAlwaysHiddenstateVisiblestateAlwaysVisibleadjustUnspecifiedadjustResizeadjustPan

stateUnspecified
中文意思是未指定狀態,當我們沒有設置 android:windowSoftInputMode 屬性的時候,軟件默認采用的就是這種交互方式,系統會根據界面采取相應的軟鍵盤的顯示模式,比如,當界面上只有文本和按鈕的時候,軟鍵盤就不會自動彈出,因為沒有輸入的必要。那麼,當界面上出現了獲取了焦點的輸入框的時候,當設置屬性為stateUnspecified的時候,系統是默認不彈出軟鍵盤的,但是當有獲得焦點的輸入框的界面有滾動的需求的時候,會自動彈出軟鍵盤。至於為什麼非要強調要獲取焦點的輸入框,這是因為,如果不是輸入框獲取焦點,軟鍵盤也是不會自動彈出的,讓界面不自動彈出軟鍵盤的其中一個解決方案,就是在xml文件中,設置一個非輸入框控件獲取焦點,從而阻止鍵盤彈出。

stateUnchanged
中文的意思就是狀態不改變的意思,我們應該怎麼理解這句話呢?其實很好理解,就是說,當前界面的軟鍵盤狀態,取決於上一個界面的軟鍵盤狀態。舉個例子,假如當前界面鍵盤是隱藏的,那麼跳轉之後的界面,軟鍵盤也是隱藏的;如果當前界面是顯示的,那麼跳轉之後的界面,軟鍵盤也是顯示狀態。

stateHidden
顧名思義,如果我們設置了這個屬性,那麼鍵盤狀態一定是隱藏的,不管上個界面什麼狀態,也不管當前界面有沒有輸入的需求,反正就是不顯示。因此,我們可以設置這個屬性,來控制軟鍵盤不自動的彈出。

stateAlwaysHidden
當該Activity主窗口獲取焦點時,軟鍵盤也總是被隱藏的

stateVisible
設置為這個屬性,可以將軟鍵盤召喚出來,即使在界面上沒有輸入框的情況下也可以強制召喚出來。

stateAlwaysVisible
這個屬性也是可以將鍵盤召喚出來,但是與stateVisible屬性有小小的不同之處。舉個例子,當我們設置為stateVisible屬性,如果當前的界面鍵盤是顯示的,當我們點擊按鈕跳轉到下個界面的時候,軟鍵盤會因為輸入框失去焦點而隱藏起來,當我們再次回到當前界面的時候,鍵盤這個時候是隱藏的。但是如果我們設置為stateAlwaysVisible,我們跳轉到下個界面,軟鍵盤還是隱藏的,但是當我們再次回來的時候,軟鍵盤是會顯示出來的。所以,這個Always就解釋了這個區別,不管什麼情況到達當前界面(正常跳轉或者是上一個界面被用戶返回),軟鍵盤都是顯示狀態。
說到這裡,我聯想到了上面的stateHidden和stateAlwaysHidden,我估計區別也是這樣的,就是說,stateAlwaysHidden無論如何都是隱藏的,但是如果在跳轉到下個界面的時候,軟鍵盤被召喚出來了,那麼當下個界面被用戶返回的時候,鍵盤應該是不會被隱藏的,但是,我還沒有找到能夠跳轉到下個界面,還讓當前界面軟鍵盤不消失的方法,所以暫時不能驗證。

adjustUnspecified
從這個屬性開始,就不是設置軟鍵盤的顯示與隱藏模式了,而是設置軟鍵盤與軟件的顯示內容之間的顯示關系。當你跟我們沒有設置這個值的時候,這個選項也是默認的設置模式。在這中情況下,系統會根據界面選擇不同的模式。如果界面裡面有可以滾動的控件,比如ScrowView,系統會減小可以滾動的界面的大小,從而保證即使軟鍵盤顯示出來了,也能夠看到所有的內容。如果布局裡面沒有滾動的控件,那麼軟鍵盤可能就會蓋住一些內容。

adjustResize
這個屬性表示Activity的主窗口總是會被調整大小,從而保證軟鍵盤顯示空間。

adjustPan
當前窗口的內容將自動移動以便當前焦點從不被鍵盤覆蓋和用戶能總是看到輸入內容的部分

Activity切換動畫

代碼
overridePendingTransition(R.anim.scale, R.anim.alpha)
xml 文件

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