【Android官方文檔】翻譯Android官方文檔-Activities(一)

Activity是可以給用戶提供交互操作的程序組件,例如打電話,拍照,發送郵件,抑或者是顯示地圖。通常窗口會填滿屏幕,但是也可以做到比屏幕小或者是懸浮在窗口頂部。

App通常由多個Activities組成,它們之間支持相互跳轉。一般情況下,每個Activity在應用中都是特別的,就好像 主Activity一樣,主activity是應用第一個Activity,其他Activity可以通過其他操作啓動。一個新的Activity的啓動,那麼舊Activity就會被停止,但是系統會保存這些activity至棧中。當一個新的activity啓動,activity被放入棧中並且操作獲得焦點,當用戶完成當前activity操作或者回退操作時,那activity將會出棧中取出,之前入棧的activity 將會被再次啓動。

當一個Activity暫停是因爲一個新的Activity的啓動,通過Activity的生命週期回調方法通知改變狀態。Activity通過系統的回調方法,去創建,銷燬,停止,恢復它。當Activity停止時,對象需要被釋放,例如網絡操作或者是數據庫操作。當Activity恢復時,你可以重新恢復獲得所需資源和輸入操作。這些狀態轉換都是生命週期的一部分。

這篇博客的其他部分會探討如何構建和使用Activity的知識。包括activity的生命週期探討,可以幫助你管理各種Activity狀態的轉換。


創建一個Activity
要創建一個activity,就需要創建一個Activity的子類(或者已經存在的子類)。在你的子類中,需要執行回調方法,來實現在其生命週期的各個狀態之間的活動轉換。例如Activity的創建,停止,恢復,或者是銷燬,下面是兩個非常重要的回調方法:

OnCreate()

這個方法是必須要去實現的,當Activity被創建的時候,系統會調用這個方法,在這個方法中,我們可以去初始化一些重要組成部分。重中之重的是,你需要調用setContentView()方法去定義一個佈局給這個Activity

OnPause()

當離開當前Activity時,會調用這個方法,注意:離開Activity的意思不僅僅是指:銷燬了Activity了。(可以是簡單的覆蓋一個Actvity時也會調用)

Activity還有其他幾個生命週期回調方法,我們應該使用它們,以達到活動之間流暢的用戶體驗,同時處理突發中斷引起你的活動被停止,甚至破壞。所有的生命週期回調方法都在後面討論。


實現用戶接口
一個Activity的用戶界面是由來自視圖類的視圖對象的層次結構提供的。每個視圖在活動窗口中控制一個特定的矩形空間,並且可以響應用戶交互。例如,一個按鈕,當用戶觸摸到它時,它就會響應一個動作。

Android提供了一些已有的View,我們可以用這些View來設計和組織我們想要的界面。”部件”是一個可視化的(互動)的屏幕元素,如按鈕、文本顯示控件、複選框,又或者只是個圖片。”Layouts“屬於ViewGroup,可以提供一個獨特的佈局,如線性佈局,網格佈局,或相對佈局。你還可以繼承View和ViewGroup類(或現有的子類)來創建自己的小部件和佈局,並把它們應用到你的Activity佈局。

最常見的方法是在XML佈局文件中構建我們的佈局,並且將其保存在應用程序的路徑下。通過這種方式,可以在源代碼中保持用戶界面的設計,在此佈局中來定義活動的行爲。我們通過setContentView()來給Activity設定佈局,設定方法是通過原先設定的ID去指向佈局文件。不過,我們也可以在Activity的代碼中新建View。

有關創建用戶界面的內容,請查看用戶界面文檔。


在配置文件中聲明Activity
想要系統可以訪問,就需要在配置文件中聲明這個Activity。打開你的配置文件,聲明方式如下:

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

這裏還有幾個其他屬性,你可以定義這些屬性,如活動的label,圖標,或主題,設定主題的用戶界面。安卓:名稱屬性是它指定活動的類名稱的唯一屬性。一旦你發佈你的應用程序,你不應該更改這個名稱,因爲如果你這樣做,你可能會破壞一些功能,如應用程序快捷方式。


使用意圖過濾器
元素也可以使用<意圖篩選器>元素指定各種意圖篩選器,以便聲明其他應用程序組件如何激活它。

當你使用Android SDK創建一個新的應用,短的活動,會自動爲你創建一個intent過濾器包括聲明活動響應的“主體”作用,應該放在“啓動”的範疇。意圖過濾器如下:

<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

元素指定了該應用程序的“主”入口點。元素指定此活動應在系統的應用程序啓動程序中列出(允許用戶啓動此項活動)。

如果你想讓你的應用程序是自包含的,不允許其他應用程序來激活它的Activity,那麼你不需要任何其他的意圖過濾器。

然而,如果你想讓你的活動響應的隱式意圖從其他應用程序交付,那麼你必須爲你的活動定義額外的意圖過濾器。對於要響應的每個類型的意圖,寫一個<意圖篩選器>,其中包含一個元素和可選的,元素和/或<數據>元素。這些元素指定了你的活動可以響應的意圖類型。


啓動Activity
你可以通過調用startActvity()來啓動另外的Activity, 在Intent對象中描述需要啓動的Activity。Intent指定要啓動或描述要執行的動作類型的確切活動(和系統爲你選擇適當的活動,這可能是來自不同的應用程序)。一個意圖也可以攜帶少量的數據。

當在你的應用程序中工作時,你通常需要簡單的啓動一個已知的Activity。你可以通過創建一個意圖,明確定義你想要開始的活動,使用這個類名稱。例如,這裏有一個活動啓動另一個活動叫signinactivity:

Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

然而,您的應用程序可能還需要執行一些操作,如發送電子郵件、文本消息或狀態更新,使用來自您的活動的數據。在這種情況下,您的應用程序可能沒有它自己的活動來執行這樣的操作,因此您可以使用其他應用程序提供的活動來進行操作,該設備可以爲您執行該操作。這是intent真正有用的地方你可以創建一個意圖,描述一個你想執行的動作,系統會從另一個應用程序的適當的活動。如果有多個可以處理該意圖的活動,則用戶可以選擇使用哪個。例如,如果您希望允許用戶發送電子郵件,您可以創建以下意圖:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

這裏extra_email額外添加的意圖是電子郵件地址。當一個電子郵件應用程序響應這個意圖時,它讀取在“to”字段的電子郵件地址。在這種情況下,電子郵件應用程序的活動開始,並且去完成郵件的發送,最後你的Activity恢復。


開啓一個帶result的Activity

有時候,你可能有一個帶result的Activity。在這種情況下,通過調用startactivityforresult()啓動活動(而不是startactivity())。然後接收來自後續Activity的result,實現onactivityresult()回調方法。

例如,也許你希望用戶從手機通訊錄中選擇聯繫人,你的Activity可以利用result這些信息做一些事情。如下:

private void pickContact() {
    // Create an intent to "pick" a contact, as defined by the content provider URI
    Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
    startActivityForResult(intent, PICK_CONTACT_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // If the request went well (OK) and the request was PICK_CONTACT_REQUEST
    if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
        // Perform a query to the contact's content provider for the contact's name
        Cursor cursor = getContentResolver().query(data.getData(),
        new String[] {Contacts.DISPLAY_NAME}, null, null, null);
        if (cursor.moveToFirst()) { // True if the cursor is not empty
            int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
            String name = cursor.getString(columnIndex);
            // Do something with the selected contact's name...
        }
    }
}

這個例子表明,你應該使用你的onactivityresult()方法,用來處理Activity的result。第一個條件檢查請求是否成功,如果是的話,那麼返回Result_OK

一個ContentResolver執行對內容提供商的查詢,並返回一個Cursor,允許被讀的數據。更多信息,參見內容提供者文檔。


銷燬Activity
你可以通過finish()方法,關掉Activity。調用finishactivity()方法,你也可以關閉一個獨立的Actvity。

注意:在大多數情況下,你不應該使用這些方法來完成一個Activity。正如下面的關於Activity生命週期的章節討論的,安卓系統爲你管理Activity的生命週期,所以你不需要finish()你自己的活動。調用這些方法可能會對預期的用戶體驗產生不利的影響。


管理Activity的生命週期
通過實現回調方法來管理Activity的生命週期,對於開發一個強大且靈活的應用程序至關重要。活動的生命週期直接影響其與其他Activity、任務和後臺的關聯。

一個Activity有三個狀態:

Resumed:
該Activity是在屏幕的頂部,並有焦點。(有時也被稱爲“運行”狀態。)
Paused:
被另一個Activity覆蓋,另一個Activity是在屏幕頂部且有焦點,但該Activity仍然是可見的。也就是說,另一個Activity是在該Activity的頂部暫停的Activity是依舊存活的(Activity對象保留在內存中,它維護所有狀態和成員信息,並保持連接到窗口管理器),但可以在極低的內存情況下被系統殺死。
Stoped:
Activity完全被另一種活動所掩蓋(當前Activity是現在的“背景”)。停止活動還活着(活動對象保留在內存中,它保持所有狀態和成員信息,但不連接到窗口管理器)。然而,它不再是可見的用戶,它可以被系統銷燬。

如果Activity被暫停或停止時,系統通過要求它完成(調用它的finish()法)來從內存中刪除它,或簡單地殺死它的進程。當活動再次打開(完成或銷燬)時,它必須被創建。


實現生命週期回調方法
當一個Activity過渡到上面描述的不同的狀態時,所有的回調方法都是hook,當你的活動狀態發生改變時,你可以重寫來做適當的工作。如下:

public class ExampleActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // The activity is being created.
    }
    @Override
    protected void onStart() {
        super.onStart();
        // The activity is about to become visible.
    }
    @Override
    protected void onResume() {
        super.onResume();
        // The activity has become visible (it is now "resumed").
    }
    @Override
    protected void onPause() {
        super.onPause();
        // Another activity is taking focus (this activity is about to be "paused").
    }
    @Override
    protected void onStop() {
        super.onStop();
        // The activity is no longer visible (it is now "stopped")
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // The activity is about to be destroyed.
    }
}

注意:你的這些生命週期方法的實現必須要做任何工作之前,調用基類的實現,如上面的示例所示。

這些方法定義的活動的整個生命週期。通過實施這些方法,可以監測活動生命週期中的三個情況:
一個Activity的整個生命週期發生oncreate()至ondestroy()。你的Activity應該執行設置“全局”的狀態(如定義佈局)在oncreate(),和ondestroy()釋放所有剩餘資源。例如,如果你的Activity有一個線程在後臺運行,從網絡上下載數據,它可能會創建線程oncreate()然後停止線程ondestroy()。
一個Activity的可視生命發生onstart()至onstop()。在此期間,用戶可以看到活動屏幕上的活動,並與之互動。例如,onstop()稱當一個新的Activity開始,這是不可見的。在這兩者之間,你可以保持需要的資源,以顯示該用戶的Activity。例如,你可以在onstart()登記一個BroadcastReceiver來監視影響你的用戶界面的變化,和註銷它onstop()當用戶無法看到你的顯示。該系統可以稱onstart()和onstop()多次Activity的整個生命週期過程中,作爲活動的交替是可見的和隱藏的用戶。
一個Activity的前臺生命發生onresume()至onpause()。在此期間,Activity是在屏幕上的所有其他活動,並具有用戶輸入焦點。

下圖說明了這些循環和路徑的活動可能採取的狀態。矩形代表在狀態之間的活動轉換時,可以實現操作的回調方法。
這裏寫圖片描述

生命週期回調方法列出在表中,更詳細的描述生命週期,並將每一個在Actviity的整個生命週期中定位。如下:
這裏寫圖片描述
這裏寫圖片描述


保存Activity狀態
管理活動生命週期的介紹中,提到當一個Activity暫停或停止時,活動的狀態被保留。這是真實的,因爲在暫停或停止所有有關其成員和當前狀態的所有信息的時候,活動對象仍然在內存中進行。因此,在活動中的用戶所做的任何更改都將保留,以便當活動返回到前臺(當它“恢復”)時,這些更改仍在那裏。

然而,當系統破壞一個活動,以便恢復內存,活動對象被破壞,所以系統不能簡單地恢復它的狀態不變。相反,系統必須重新創建活動對象,如果用戶導航回到它。然而,用戶不知道系統銷燬活動並重新創建它,因此,可能希望活動要完全一樣。在這種情況下,你可以確保重要活動的相關信息是通過實施一個附加的方法,允許你保存你的活動的狀態信息保存:onsaveinstancestate()。

系統調用onsaveinstancestate()保存用戶中斷操作前的狀態。系統通過這一方法,你能保存活動的狀態信息作爲名稱值對,使用方法如putstring()和putint()。然後,如果系統殺死你的應用程序進程和用戶導航回到你的活動,系統會重新創建活動並通過oncreate()和onrestoreinstancestate()使用這些方法中的一個恢復之前的狀態。你可以提取你的保存狀態,並恢復Activity狀態。如果沒有狀態信息來恢復,那麼返回參數將會是空的(第一次創建活動時的情況下參數是空的)。
這裏寫圖片描述

然而,即使你什麼也不做,不執行onsaveinstancestate(),某些活動狀態也是會由onsaveinstancestate()活動類的默認實現恢復。具體來說,默認的實現需要佈局中的每個視圖對應的onsaveinstancestate()方法,允許每個視圖提供關於自身的信息對應保存。在Android框架中,幾乎每一個部件合理地實現這個方法,這樣對用戶界面的任何可見的變化都是可以自動保存的,並且可以恢復Activity被重新創建時的狀態。

因爲onsaveinstancestate()默認的實現有助於同步UI的狀態,重寫這些方法,可以節省額外的保存狀態信息,在做任何操作前,onsaveinstancestate()調用實現。然後你重寫onrestoreinstancestate(),就可以實現還原視圖狀態。

注:onsaveinstancestate()並不能保證在任何情況下都可以做到狀態的恢復,這隻能用來記錄Activity的瞬態,不應該用它來存儲持久化數據。正確的做法是:當用戶離開活動時,使用onpause()存儲持久化數據(如數據應保存到數據庫)。

有一個很好的方法,可以來測試你的應用程序的恢復狀態的能力:簡單地旋轉設備,使屏幕方向的變化。當屏幕的方向改變時,系統銷燬並重新創建Activity,這是非常重要的,你的活動完全恢復狀態時,它是重現的,因爲用戶在使用應用時經常旋轉屏幕。


處理配置的變化
一些設備配置可以在運行時改變(如屏幕方向,軟鍵盤)。當發生這樣的變化時,Android重新運行的Activity(系統調用ondestroy(),然後立即調用oncreate())。這種行爲的目的是幫助您的應用程序的自動加載與替代資源,適應設備的變化,
如果你正確地設計你的Activity來處理一個重新啓動,當屏幕方向等狀況改變,你的應用程序將更靈活處理這種情況。
最好的解決方式是保存和恢復你的活動中使用onsaveinstancestate(), onrestoreinstancestate()(或oncreate()),如在上面有提到)。


協調活動

當一個Activity開始至另一個Activity,這個過程就是生命週期狀態的轉變。第一個活動銷燬和暫停(它不是已銷燬,仍然是可見的背景),重要的是要了解,第一個Activity是不完全停止的。相反,啓動第二個Activity的過程中,是第一個Activity重疊的過程。


以上是Android官方文檔Activity部分的簡單翻譯,勿噴~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章