Android: Activity、進程、BoradcastReceiver生命週期

Android中Activity和進程的生命週期是一個很重要的問題。Android對進程也採取了垃圾回收之類的機制,這意味着即使用戶退出了程序,該進程依然可能存在於系統中。這將直接影響我們寫的程序結構。

[color=red]
一個進程可能有若干個Activity。Activity退出後,進程可能並沒有結束。下次用戶從桌面啓動該Activity時,會直接使用沒有結束的進程。所以,想直接在主Activity中做程序初始化之類的操作,則需要小心。(實際上,Activity沒有主次之分,說它是“主”,主要是因爲它接受ndroid.intent.action.MAIN action)
[/color]

如下代碼:
[code]
package com.kl.test;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

class GlobalData {
public static final String LOGTAG = "TestLog";
private static GlobalData mInst = null;

public static GlobalData instance() {
if(mInst == null) {
Log.d(LOGTAG, "The instance is null.");
mInst = new GlobalData();
}
else {
Log.d(LOGTAG, "The instance is ready.");
}
return mInst;
}
}

public class Test2 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(GlobalData.LOGTAG, "Activity onCreate.");
GlobalData.instance();
Observer.register(this);
}

@Override
protected void onDestroy() {
super.onDestroy();
Log.d(GlobalData.LOGTAG, "Activity onDestroy.");
}
}
[/code]

[code]
package com.kl.test;

import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;

/*
* If the process has been terminated, the ContentObserver will not be called when
* the content changed.
* It's very same as Activity about life cycle.
*/
public class Observer extends ContentObserver {
private static final Uri CONTENT_URI = Uri.parse("content://sms");
private static boolean mRegistered = false;

Observer(Handler h) {
super(h);
}

@Override
public void onChange( boolean selfChange ) {
super.onChange(selfChange);
Log.d(GlobalData.LOGTAG, "Observer onChange.");
// test code.
GlobalData.instance();
}

public static void register(Context context) {
if(mRegistered) {
Log.d(GlobalData.LOGTAG, "Observer already registered.");
return;
}
mRegistered = true;
context.getContentResolver().registerContentObserver(CONTENT_URI, true,
new Observer( new Handler() ) );
Log.d(GlobalData.LOGTAG, "Observer register.");
}
}

[/code]

GlobalData算是我們程序的邏輯數據,當運行以上程序時,第一次會得到如下日誌輸出:

[code]
12-24 11:58:58.923: DEBUG/TestLog(223): Activity onCreate.
12-24 11:58:58.983: DEBUG/TestLog(223): The instance is null.
12-24 11:58:59.014: DEBUG/TestLog(223): Observer register.
[/code]

ContentObserver是當監聽的content發生變化時,被回調。當按BACK回到桌面,並再次啓動該程序時,則得到:

[code]
12-24 12:09:14.113: DEBUG/TestLog(223): Activity onCreate.
12-24 12:09:14.134: DEBUG/TestLog(223): The instance is ready.
12-24 12:09:14.154: DEBUG/TestLog(223): Observer already registered.
[/code]

從上可以證實:
[color=red]
就算是activity都退出了,進程也不一定結束。進程不結束,進程內的靜態數據就不會消失。[/color]

進程什麼時候被終止?根據官方文檔描述,一個重要的條件是,當系統發覺內存過少時,則會把一些沒有處於前臺的activity進程結束掉。我們可以使用DDMS直接終止進程。終止進程後,再啓動activity,則會得到第一次的日誌輸出。

[color=red]
值得注意的是,如果我們的進程結束掉了,那麼註冊的ContentObserver則不會被調用。相反,如果進程依然存在,就算沒有activity,ContentObserver也會被調用,並且不會創建其他activity。
[/color]

此外,對於BroadcastReceiver:
[code]
package com.kl.test;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/*
* It will called even if the process has been terminated before. After it is called,
* the process will remain as usual for sometime.
*/
public class SmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(GlobalData.LOGTAG, "SmsReceiver onReceive.");
GlobalData.instance();
}
}

[/code]

[color=red]
就算進程不在,BroadcastReceiver也會被調用,並且創建對應的進程。但是,並不會創建任何Activity。
[/color]


[color=red]
BTW,activity中的數據會由於activity被銷燬而被銷燬。activity onDestroy了就真的是被destory了,意味着其在內存中的消失。在UI中緩存UI界面數據的需要注意一下。
[/color]

PS,優化後的程序在進程已經存在的情況下,效率明顯提升。:D

[color=red]
1.16.2011 update[/color]
BroadcastReceiver被調用時,會首先初始化所在的進程(如果進程之前被關閉),也就是會執行Application:onCreate
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章