官方解讀Activity之二

來源:互聯網
上載者:User

本文接著上一篇寫:

配置改變
如果裝置的配置(被定義為Resources.Configuration類)被改變了,那麼所有顯示使用者介面的都需要被更新以適應新的配置。因為Acitivity是和使用者互動的首要機制,它包含了對設定檔改變的特殊支援。
除非你特殊指定,否則,設定檔的改變將會導致你當前的activity被銷毀,經曆了一個正常的activity的生命週期:onPause()、onStop(0和onDestroy()。如果此activity目前處在螢幕的最前端,或者是對使用者可見,一旦那個activity執行個體的onDestroy()被調用,那麼一個新的activity執行個體將會被建立,並且新建立的執行個體將會從 onSaveInstanceState(Bundle)中獲得之前那個activity的狀態。為什麼要這麼做呢?是因為任何應用程式的資源,包括布局檔案,都能夠因為任何設定檔中的配置值而發生改變。因此,對待設定檔的改變最保險的方式就是重新獲得所有的資源,包括布局檔案,圖片資源以及字元資源。由於activity一定知道如何儲存他們自己的狀態並且利用這些狀態重新建立自己,這就是一個簡便的方法,讓activity利用新的設定檔重啟自己!
在一些特殊的情況下,你可能想基於一種或者多種設定檔的改變而避開重啟你的activity,這可以通過manifest檔案中的 android:configChanges屬性來實現。對你聲明在此的任何類型的設定檔的改變,你都將再你的activity中調用onConfigurationChanged(Configuration)方法,而不是通常的重啟行為。如果出現了一些你並未在此聲明的設定檔改變類型,那麼,此activity將會重啟並且onConfigurationChanged(Configuration)將不會被調用!
啟動Activities並擷取結果
startActivity(Intent)方法被用來啟動一個新的activity,新啟動的activity將會位於棧頂,該方法僅有一個參數,一個 Intent,該Intent被用來描述即將被啟動的那個activity。
有的時候你也許希望當一個activity結束的時候可以從期中獲得一個結果。例如:你可能會啟動一個activity使得使用者可以從連絡人清單中選取一個記錄,當選取結束後,該activity可以返回你選中的記錄。為了達到這樣的目的,你可以調用startActivityForResult(Intent, int)這個方法來啟動activity,該方法包含第二個參數,用於標識本次調用的一個整數,該方法的傳回值會通過 onActivityResult(int, int, Intent)方法返回。
當一個activity已經存在,那麼他就可以調用setResult(int)返回資料給它的持有人,他必須總是提供一個返回碼,可以使標準的結果RESULT_CANCELED, RESULT_OK或者是任何從RESULT_FIRST_USER開始自訂的代碼。另外,它可以返回一個可選的intent,這個intent可以包含任何你想要的資料。所有的這些資訊都會返回給它的持有人的Activity.onActivityResult(),伴隨著前面提到的整型參數。
如果一個子activity由於任何原因失敗了(例如:崩潰),那麼父activity將會收到RESULT_CANCELED的返回碼。

 

public class MyActivity extends Activity { 
     ... 
 
     static final int PICK_CONTACT_REQUEST = 0; 
 
     protected boolean onKeyDown(int keyCode, KeyEvent event) { 
         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { 
             // When the user center presses, let them pick a contact. 
             startActivityForResult( 
                 new Intent(Intent.ACTION_PICK, 
                 new Uri("content://contacts")), 
                 PICK_CONTACT_REQUEST); 
            return true; 
         } 
         return false; 
     } 
 
     protected void onActivityResult(int requestCode, int resultCode, 
             Intent data) { 
         if (requestCode == PICK_CONTACT_REQUEST) { 
             if (resultCode == RESULT_OK) { 
                 // A contact was picked.  Here we will just display it 
                 // to the user. 
                 startActivity(new Intent(Intent.ACTION_VIEW, data)); 
             } 
         } 
     } 
 } 
public class MyActivity extends Activity {
     ...

     static final int PICK_CONTACT_REQUEST = 0;

     protected boolean onKeyDown(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
             // When the user center presses, let them pick a contact.
             startActivityForResult(
                 new Intent(Intent.ACTION_PICK,
                 new Uri("content://contacts")),
                 PICK_CONTACT_REQUEST);
            return true;
         }
         return false;
     }

     protected void onActivityResult(int requestCode, int resultCode,
             Intent data) {
         if (requestCode == PICK_CONTACT_REQUEST) {
             if (resultCode == RESULT_OK) {
                 // A contact was picked.  Here we will just display it
                 // to the user.
                 startActivity(new Intent(Intent.ACTION_VIEW, data));
             }
         }
     }
 }
儲存連續的狀態
activity一般需要處理兩種持續的狀態:一種是共用的文件類型的資料(典型的是利用content_provider儲存再SQLite中);另一種是內部狀態例如:使用者的偏好。
對於content provider資料,建議activities利用本地編輯的模型。那就是,使用者做出的任何編輯都會立即產生作用,而不需要額外的確認的步驟,支援這種模型需要遵守如下兩條規則:
1、當建立一個新的文檔,那麼備份的資料庫條目和檔案就會立即被建立。例如:當使用者要寫一個新的郵件時,那麼一條新的記錄就會隨著開始輸入資料而被建立,以至於如果使用者瀏覽其他的activity,這個郵件將會出現在草稿箱中。
2、當activity的onPause()方法被調用,那麼他就會把使用者做出的任何改變提交到後端的content provider或者是檔案。這將會確保那些改變對於那些即將啟動並執行activity是可見的,你可能會想在activity的生命週期中更加積極主動的儲存資料,例如:在啟動一個新的activity之前,在結束一個activity之前,當使用者改變輸入框時。
這個模型被設計用來在使用者瀏覽多個activity防址資料的丟失,並且允許系統在activity被暫停之後安全的殺死它。這意味著使用者按下BACK鍵並不意味著“取消”,而是意味著儲存當前的activity的內容並且離開當前的activity,在一個activity中取消編輯需要通過其他的一些機制,例如一個明確的“恢複”或者“撤銷”選項。
關於content providers的詳細內容可以查閱 content package,這些都是關於在activities之間調用和傳播資料的不同之處重要方面。
Activity同樣提供了API來管理與activity有關聯的持續的狀態。這都是可以被拿來使用的,例如:要記住使用者的日曆顯示(日視圖還是周視圖)或者瀏覽器的預設首頁。
Activity持久的狀態是通過getPreference(int)來管理的,允許你去擷取並修改一系列和activity有關的索引值對。對於多個應用程式組件(activities,receivers,services,provides)共用的喜好設定,你可以通過隱含的Context.getSharedPreferences()方法來通過特殊的名字擷取喜好設定的一些對象。(注意:再多個應用程式套件組合中共用設定的資料是不可能的,對於這種情況,你需要使用content provider).
下面有一個從存有使用者設定的顯示模式的calendar activity中摘抄的一些內容:

 

public class CalendarActivity extends Activity { 
     ... 
 
     static final int DAY_VIEW_MODE = 0; 
     static final int WEEK_VIEW_MODE = 1; 
 
     private SharedPreferences mPrefs; 
     private int mCurViewMode; 
 
     protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
 
         SharedPreferences mPrefs = getSharedPreferences(); 
         mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE); 
     } 
 
     protected void onPause() { 
         super.onPause(); 
  
         SharedPreferences.Editor ed = mPrefs.edit(); 
         ed.putInt("view_mode", mCurViewMode); 
         ed.commit(); 
     } 
 } 
public class CalendarActivity extends Activity {
     ...

     static final int DAY_VIEW_MODE = 0;
     static final int WEEK_VIEW_MODE = 1;

     private SharedPreferences mPrefs;
     private int mCurViewMode;

     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         SharedPreferences mPrefs = getSharedPreferences();
         mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE);
     }

     protected void onPause() {
         super.onPause();
 
         SharedPreferences.Editor ed = mPrefs.edit();
         ed.putInt("view_mode", mCurViewMode);
         ed.commit();
     }
 }
許可權
啟動特殊activity的權利是在manifest檔案中的<activity>標籤中聲明後被強制執行的。通過這種做法,其他的應用程式需要再他們自己的manifest檔案中聲明相應的<uses-permission>元素才能啟動上面所說的特殊的activity。

要想查看詳細的關於許可權和安全的內容,可以查閱Security and Permissions文檔。

 


進程的生命週期
Android系統試圖儘可能的保持進程,但是不幸的是,當系統記憶體過低時,系統不得不殺死一些老的進程來釋放記憶體空間。進程也有四種狀態,這四種狀態都是基於運行再進程中的activity的狀態,系統會優先殺死一些不太重要的進程而不是殺死重要的進程。
1、前台的activity
2、可見的activity
3、背景activity
4、空的進程
有的時候,一個Activity也許需要長時間的運行,即要獨立的存在於它自己的activity生命週期,一個例子就是:也許照相的應用程式允許你上傳照片到網上,而上傳可能會需要比較長的時間,那麼這個應用程式應當允許使用者離開上傳照片的activity,但是上傳照片的進程還是要處於運行狀態。為了達到這樣的目的,你的應用程式需要再你上傳照片的地方開啟一個service。這就允許系統給你的應用賦於恰當的優先順序,獨立於你原來的activity,不管原來的activity處於paused、stopped或者是finished。

摘自 chenlong12580的專欄

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.