1. 程式人生 > >談一談對Activity的理解

談一談對Activity的理解

一、Activity的生命週期

Activity的基本生命週期如下程式碼 所示:

public class MyActivity extends Activity {   

    protected void onCreate(Bundle savedInstanceState);   

    protected void onStart();   

    protected void onResume();   

    protected void onPause();   

    protected void onStop();   

    protected void
onDestroy(); }

詳細介紹一下這幾個方法中系統在做什麼以及我們應該做什麼:
- onCreate:在這裡建立介面 ,做一些資料 的初始化工作。
- onStart:到這一步變成使用者可見不可互動的。
- onResume:變成和使用者可互動的,在activity棧系統通過棧的方式管理這些個Activity的最上面,執行完彈出棧,則回到上一個Activity。
- onPause:到這一步是可見但不可互動的,系統會停止動畫等消耗CPU 的事情。從上文的描述已經知道,應該在這裡儲存你的一些資料,因為這個時候你的程式的優先順序降低,有可能被系統收回。在這裡儲存的資料,應該在onResume裡讀出來。注意:這個方法裡做的事情時間要短,因為下一個activity不會等到這個方法完成才啟動。


- onStop:變得不可見 ,被下一個activity覆蓋了。
- onDestroy:這是activity被幹掉前最後一個被呼叫方法了,可能是外面類呼叫finish方法或者是系統為了節省空間將它暫時性的幹掉,可以用isFinishing()來判斷它,如果你有一個Progress Dialog線上程中轉動,請在onDestroy裡把他cancel掉,不然等執行緒結束的時候,呼叫Dialog的cancel方法會拋異常的。

onPause,onStop, onDestroy,三種狀態 下 activity都有可能被系統幹掉。為了保證程式的正確性,你要在onPause()裡寫上持久層操作的程式碼,將使用者編輯的內容都儲存到儲存介質上(一般都是資料庫 )。實際工作中因為生命週期的變化而帶來的問題也很多,比如你的應用程式起了新的執行緒在跑,這時候中斷了,你還要去維護那個執行緒,是暫停還是殺掉還是資料回滾,是吧?因為Activity可能被殺掉,所以執行緒中使用的變數和一些介面元素就千萬要注意了,一般我都是採用Android的訊息機制 [Handler,Message]來處理多執行緒和介面互動的問題。這個我後面會講一些,最近因為這些東西頭已經很大了,等我理清思緒再跟大家分享。

二、讓Activity變成一個視窗:Activity屬性設定

講點輕鬆的吧,可能有人希望做出來的應用程式是一個漂浮在手機主介面的東西,那麼很簡單你只需要設定 一下Activity的主題就可以了在AndroidManifest.xml 中定義 Activity的地方一句話:

android:theme="@android:style/Theme.Dialog" 
// 這就使你的應用程式變成對話方塊的形式彈出來了,或者
android:theme="@android:style/Theme.Translucent" 
// 就變成半透明的

【友情提示】類似的這種activity的屬性可以在android.R.styleable 類的AndroidManifestActivity 方法中看到,AndroidManifest.xml中所有元素的屬性的介紹都可以參考這個類android.R.styleable。上面說的是屬性名稱,具體有什麼值是在android.R.style中 可以看到,比如這個”@android:style/Theme.Dialog” 就對應於android.R.style.Theme_Dialog。

三、你後臺的Activity被系統回收怎麼辦:onSaveInstanceState

當你的程式中某一個Activity A 在執行時中,主動或被動地執行另一個新的Activity B,這個時候A會執行onSaveInstanceState方法。

public
void onSaveInstanceState(Bundle outState) {   
    super.onSaveInstanceState(outState);   
    outState.putLong("id", 1234567890);   
}  

B 完成以後又會來找A,這個時候就有兩種情況,一種是A被回收,一種是沒有被回收,被回收的A就要重新呼叫onCreate()方法,不同於直接啟動的是這回onCreate()裡是帶上引數savedInstanceState,沒被收回的就還是onResume就好了。
savedInstanceState是一個Bundle物件,你基本上可以把他理解為系統幫你維護的一個Map物件。在onCreate裡你可能會用到它,如果正常啟動onCreate就不會有它,所以用的時候要判斷一下是否為空。

if (savedInstanceState != null) {   
     long id = savedInstanceState.getLong("id");   
}   

onSaveInstanceState(Bundle outState)方法在onPause()之後呼叫的。
就像官方的Notepad教程 裡的情況,你正在編輯某一個note,突然被中斷,那麼就把這個note的id記住,再起來的時候就可以根據這個id去把那個note取出來,程式就完整一些。這也是看你的應用需不需要儲存什麼,比如你的介面就是讀取一個列表,那就不需要特殊記住什麼,哦, 沒準你需要記住滾動條的位置…

四、呼叫與被呼叫:我們的通訊使者Intent

要說Intent了,Intent就是這個這個意圖 ,應用程式間Intent進行交流,打個電話啦,來個電話啦都會發Intent,這個是Android架構的鬆耦合的精髓部分,大大提高了元件的複用性,比如你要在你的應用程式中點選按鈕,給某人打電話,很簡單啊,看下程式碼先:

Intent intent = new Intent();   
intent.setAction(Intent.ACTION_CALL);   
intent.setData(Uri.parse("tel:" + number));   
startActivity(intent);  

扔出這樣一個意圖,系統看到了你的意圖就喚醒了電話撥號程式,打出來電話。什麼讀聯絡人,發簡訊啊,郵件啊,統統只需要扔出intent就好了,這個部分設計 地確實很好啊。
那Intent通過什麼來告訴系統需要誰來接受他呢?通常使用Intent有兩種方法,第一種是直接說明需要哪一個類來接收程式碼如下:

Intent intent = new Intent(this, MyActivity.class);   
intent.getExtras().putString("id", "1");   
startActivity(intent); 

第一種方式很明顯,直接指定了MyActivity為接受者,並且傳了一些資料給MyActivity,在MyActivity裡可以用getIntent()來的到這個intent和資料。
第二種就需要先看一下AndroidMenifest中的intent-filter的配置了:

<intent-filter> 
    <action android:name="android.intent.action.VIEW" /> 
    <action android:value="android.intent.action.EDIT" /> 
    <action android:value="android.intent.action.PICK" /> 
    <category android:name="android.intent.category.DEFAULT" /> 
    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> 
</intent-filter> 

action其實就是一個意圖的字串名稱。
上面這段intent-filter的配置檔案說明了這個Activity可以接受不同的Action,當然相應的程式邏輯也不一樣咯,提一下那個 mimeType,他是在ContentProvider裡定義的,你要是自己實現一個ContentProvider就知道了,必須指定 mimeType才能讓資料被別人使用。不知道原理說明白沒,總結一句,就是你呼叫別的介面不是直接new那個介面,而是通過扔出一個intent,讓系統幫你去呼叫那個介面,這樣就多麼鬆藕合啊,而且符合了生命週期被系統管理的原則。想知道category都有啥,Android為你預先定製好的action都有啥等等,請親自訪問官方連結Intent 。

ps:想知道怎麼呼叫系統應用程式的同學,可以仔細看一下你的logcat,每次執行一個程式的時候是不是有一些資訊比如:
Starting activity: Intent { action=android.intent.action.MAINcategories={android.intent.category.LAUNCHER} flags=0x10200000comp={com.android.camera/com.android.camera.GalleryPicker} }
再對照一下Intent的一些set方法,就知道怎麼呼叫咯,希望你喜歡:)