android activity

本文详细介绍Android平台中Activity的生命週期,包括Activity的各种状态及其转换过程,并通过实例代码演示了不同状态下Activity的行为。

Activity 的生命週期
作者: gasolin
日期: 2010-03-03
本文详细介绍了 Activity 的生命周期,非常明了。
生命週期

作者在初級章節中一直努力地傳達給讀者:編寫 Android 平台的基本應用程式,跟編寫桌面應用程式的難度,兩者並沒什麼不同。甚至因為 Android 平台擁有免費、跨平台的開發工具,使得 Android 平台應用程式的開發更為單純。

但是請別忘了,Android 平台也是個手機作業系統。撇掉其他功能不談,手機的特性,就是應該能隨時在未完成目前動作的時候,離開正在使用的功能,切換到接電話、接收簡訊模式...而且在接完電話回來應用程式時,還希望能看到一樣的內容。

現在使用者使用智慧型手機,大多已習慣使用多工(Multi-Task)的作業系統(如 Windows Mobile),可以在用手機聽音樂的同時,也執行其他多個程式。同時執行多個程式有它的明顯好處,但是也有它的嚴重的缺點。每多執行一個應用程式,就會多耗費一些系統記憶體。而手機裡的記憶體是相當有限的。當同時執行的程式過多,或是關閉的程式沒有正確釋放掉記憶體,執行系統時就會覺得越來越慢,甚至不穩定。

為了解決這個問題, Android 引入了一個新的機制 — 生命週期 (Life Cycle)。

行程

應用程式(一個個 Activity)執行的狀態稱為行程(process)。在 Android 作業系統中,每個應用程式都是一個行程。Android 系統平台(準確的說是 Dalvik 虛擬機)會維護一個唯一的 Activity 歷史記錄堆疊,並從旁觀察每個應用程式行程。系統平台會依照系統的記憶體狀況,與 Activity 的使用狀態,來管理記憶體的使用。

Activity 類別除了負責運行程式流程,與操作介面元件之外,最重要的,就是它提供了開發者控制行程生命週期的函式。我們已經相當習慣在 OnCreate (建立行程時的行為)函式中,加入我們對這個 Activity 執行流程的控制。在前面遇到的範例中,我們並不需要對除了 OnCreate 之外的行為做出改變。不過理解行程的生命週期,將為我們繼續深入 Android 開發打下基礎。

為什麼要了解生命週期

Android 應用程式的生命週期是由 Android 框架進行管理,而不是由應用程式直接控制。

通常,每一個應用程式(入口一般會是一個 Activity 的 onCreate 方法),都會佔據一個行程(Process)。當系統記憶體即將不足的時候,會依照優先級自動進行行程(process)的回收。不管是使用者或開發者,都無法確定的應用程式何時會被回收。

一個 Activity 類別除了 OnCreate 函式之外,還預先定義了 OnPause(暫停行程時的行為)、OnResume(繼續行程時的行為)等等的基本行為,當從一個 Activity 切換到另一個 Activity 的時候,原本的 Activity 將經過一連串的狀態改變。開發者可以在程式中添加一些各狀態相對應的流程,每次 Activity 改變狀態時,就會執行相對應的流程。

要讓使用者有好的使用經驗,Activity 需要在各個週期點上負責保管狀態、恢復狀態、傳送資料等工作。

Activity 的狀態

Android 的虛擬機(VM)是使用堆疊 (Stack based) 管理。主要有四種狀態:

  1. Active (活動)
  2. Paused (暫停)
  3. Stopped (停止)
  4. Dead (已回收或未啟動)
Active (活動)

「Active」狀態是使用者啟動應用程式或 Activity 後,Activity 運行中的狀態。

Android 平台上,同一個時刻只會有一個 Activity 處於活動(Active)或運行(Running)狀態。其他的 Activity 都處於未啟動(Dead)、停止(Stopped)、或是暫停(Pause)的狀態。

Paused (暫停)

「Paused」狀態是當 Activity 暫時暗下來,退到背景畫面的狀態。

當我們使用Toast、AlertDialog、或是電話來了時,都會讓原本運行的 Activity 退到背景畫面。新出現的Toast、AlertDialog等介面元件蓋住了原來的 Activity 畫面。Activity 處在「Paused」狀態時,使用者無法與原 Activity 互動。

Stopped (停止)

「Stopped」狀態是有其他 Activity 正在執行,而這個 Activity 已經離開螢幕,不再動作的狀態。

透過長按「Home」鈕,可以叫出所有處於「Stopped」狀態的應用程式列表。

在「Stopped」狀態的 Activity,還可以透過「Notification」來喚醒。「Notification」會在後面章節中解說。

Dead (已回收或未啟動)

「Dead」狀態是 Activity 尚未被啟動、已經被手動終止,或已經被系統回收的狀態。

要手動終止 Activity,可以在程式中呼叫「finish」函式。

如果是被系統回收,可能是因為記憶體不足了,所以系統根據記憶體不足時的回收規則,將處於「Stopped」狀態的 Activity 所佔用的記憶體回收。

記憶體不足時的行為

記憶體不足時,Dalvik 虛擬機會根據其記憶體回收規則來回收記憶體:

  1. 先回收與其他 Activity 或 Service/Intent Receiver 無關的行程(即優先回收獨立的Activity);
  2. 再回收處於「Stopped」狀態的其他類型 Activity(在背景等待的Activity)。最久沒有使用的 Activity 優先回收(比較官方的說法是 "根據 LRU 演算法...");
  3. 還不夠?回收 Service 行程;
  4. 快不行啦,關掉可見的 Activity/行程;
  5. 關閉當前的 Activity 。

當系統缺記憶體缺到開始「4. 關掉可見的 Activity/行程」時,大概我們換機子的時機也早該到啦!

觀察 Activity 運作流程

講了這麼多虛的,我們可以寫一些程式來直觀查看 Activity 的運作流程嗎?

當然可以。在上一章記錄與偵錯 (Log)中,我們學到的「Log」工具,正好可以在查看 Activity 的運作流程時派上用場。

打開「src/com/demo/android/bmi/Bmi.java」,在程式中加入一些「Log」記錄點:

public class Bmi extends Activity {
        private static final String TAG = "Bmi";

    public void onCreate()
    {
        super.onCreate(...);
        Log.v(TAG,"onCreate");
    }

    public void onStart()
    {
        super.onStart();
        Log.v(TAG,"onStart");
    }

    public void onResume()
    {
        super.onResume();
        Log.v(TAG,"onResume");
    }

    public void onPause()
    {
        super.onPause();
        Log.v(TAG,"onPause");
    }

    public void onStop()
    {
        super.onStop();
        Log.v(TAG,"onStop");
    }

    public void onRestart()
    {
        super.onRestart();
        Log.v(TAG,"onReStart");
    }

    public void onDestroy()
    {
        super.onDestroy();
        Log.v(TAG,"onDestroy");
    }

}

講解

我們為 Activity 的各個狀態加入了「Log」記錄訊息。當模擬器運行時,我們可以透過 「LogCat」工具來查看 Activity 所處在的狀態。

上面的七個狀態又可以歸納成三組:

1. 資源分配 (Create/Destroy)

完整的 Activity 生命週期由「Create」狀態開始,由「Destroy」狀態結束。建立(Create)時分配資源,銷毀(Destroy)時釋放資源。

2. 可見與不可見(Start/ReStart/Stop)

當 Activity 運行到「Start」狀態時,就可以在螢幕上看到這個 Activity。相反地,當Activity 運行到「Stop」狀態時,這個 Activity 就會從螢幕上消失。

當使用者按下 Back 按鈕回到上一個 Activity 時,會先到 Restart 狀態,再到一般的 Start 狀態。

3. 使用者能否直接存取螢幕(Resume/Pause)

當有個 Toast、AlertDialog、簡訊、電話等訊息亂入時,原來的 Activity 會進入「Pause」狀態,暫時放棄直接存取螢幕的能力,被中斷到背景去,將前景交給優先級高的事件。當這些優先級高的事件處理完後,Activity 就改進入「Resume」狀態,此時又直接存取螢幕。

Activity 運作流程

由實際運行的記錄來看,我們可以歸納出所有 Android 應用程式都遵循的動作流程:

一般啟動
onCreate -> onStart -> onResume

啟動一個 Activity 的基本流程是:分配資源給這個 Activity(Create 狀態),然後將 Activity 內容顯示到螢幕上(Start 狀態)。在一切就緒後,取得螢幕的控制權(Resume 狀態),使用者可以開始使用這個程式。

呼叫另一個 Activity
onPause(1) -> onCreate(2) -> onStart(2) - onResume(2) -> onStop(1)

這是個先凍結原本的 Activity,再交出直接存取螢幕能力(Pause 狀態)的過程。 直到 Activity 2 完成一般啟動流程後,Activity 1 才會被停止。

回原 Activity
onPause(2) -> onRestart(1) -> onStart(1) -> onResume(1) -> onStop(2) -> onDestroy(2)

點 Back 按鈕可以回到原本的 Activity。

退出結束
onPause -> onStop -> onDestroy

如果程式中有直接呼叫「finish」函式來關閉 Activity的話,系統假設我們很確定我們在做什麼,因此會直接跳過先凍結(Freeze)的階段,暫停(Pause),停止(Stop),然後銷毀(Destroy)。

回收後再啟動
onCreate -> onStart -> onResume

被回收掉的 Activity 一旦又重新被呼叫時,會像一般啟動一樣再次呼叫 Activity 的 onCreate 函式。

當我們使用「Android」手機一陣子,在手機上已經執行過多個應用程式。只要按下「Back」(返回)鍵,「Android」就會開啟最近一次開啟過的 Activity。

這時我們要是按下多次「Back」(返回)鍵,理論上遲早會返回到某個已經銷毀(Destroy)的 Activity。這時會發生什麼事呢?

如果應該開啟的 Activity 已經被回收了,那麼這個 Activity 會再次被建立(Create)出來。再次被建立出來的 Activity,當然會跟原本我們開啟過的 Activity 不一樣啦。

所以如果要讓再次被建立出來的 Activity 看起來跟原本開啟過的一樣,那麼在 Activity 之間切換時,我們就要留意保留資料:最好在每次 Activity 運行到「onPause」或「onStop」狀態時先保存資料,然後在「onCreate」時將資料讀出來。

Back 按键的处理

当按下 Back 按钮时,将进程杀掉,虽然这种方法比较野蛮,但也是一种办法。流程如下所示:

onKeyBackDown -> finish() -> onDestroy -> kill process

示例代码如下所示:

public boolean onKeyDown(int keyCode, KeyEvent event) {

    if (keyCode == KeyEvent.KEYCODE_BACK) {
        finish ();
    }

}

 @Override
 protected void onDestroy() {
    super.onDestroy();
    //Kill myself
    android.os.Process.killProcess(android.os.Process.myPid());
 }


参考资料

原文

 

 

对手机有所研究的朋友们,应该对于Android这一手机操作系统并不陌生。它是一款基于Linux平台的开源手机操作系统。我们在这里会通过对Android Activity生命周期的介绍来充分的了解一下这一系统的基本原理。

注意到在Activity的API中有大量的onXXXX形式的函数定义,除了我们前面用到的onCreate以外,还有onStart,onStop以及onPause等等。从字面上看,它们是一些事件回调,那么次序又是如何的呢?其实这种事情,自己做个实验最明白不过了。在做这个实验之前,我们先得找到在Android中的Log是如何输出的。

显然,我们要用的是android.util.log类,这个类相当的简单易用,因为它提供的全是一些静态方法:

 
  1. Log.v(String tag, String msg); //VERBOSE  
  2. Log.d(String tag, String msg); //DEBUG   
  3. Log.i(String tag, String msg); //INFO  
  4. Log.w(String tag, String msg); //WARN  
  5. Log.e(String tag, String msg); //ERROR 

前面的tag是由我们定义的一个标识,一般可以用“类名_方法名“来定义。

输出的LOG信息,如果用Eclipse+ADT开发,在LogCat中就可以看到,否则用adb logcat也行,不过我是从来都依赖于IDE环境的。

好了,现在我们修改前面的HelloThree代码:

 
  1. public void onStart()  
  2. ...{  
  3. super.onStart();  
  4. Log.v(TAG,"onStart");  
  5. }  
  6. public void onStop()  
  7. ...{  
  8. super.onStop();  
  9. Log.v(TAG,"onStop");  
  10. }  
  11. public void onResume()  
  12. ...{  
  13. super.onResume();  
  14. Log.v(TAG,"onResume");  
  15. }  
  16. public void onRestart()  
  17. ...{  
  18. super.onRestart();  
  19. Log.v(TAG,"onReStart");  
  20. }  
  21. public void onPause()  
  22. ...{  
  23. super.onPause();  
  24. Log.v(TAG,"onPause");  
  25. }  
  26. public void onDestroy()  
  27. ...{  
  28. super.onDestroy();  
  29. Log.v(TAG,"onDestroy");  
  30. }  
  31. public void onFreeze(Bundle outState)  
  32. ...{  
  33. super.onFreeze(outState);  
  34. Log.v(TAG,"onFreeze");  

在HelloThreeB中也同样增加这样的代码,编译,运行一下,从logcat中分析输出的日志。

在启动第一个界面Activity One时,它的次序是:

 
  1. onCreate (ONE) - onStart (ONE) - onResume(ONE)  


虽然是第一次启动,也要走一遍这个resume事件。然后,我们点goto跳到第二个Activity Two中(前一个没有关闭),这时走的次序是:

 
  1. onFreeze(ONE) - onPause(ONE) - onCreate(TWO) -  onStart(TWO) - onResume(TWO) - onStop(ONE) 

说明,第二个Activity Two在启动前,One会经历一个:冻结、暂停的过程,在启动Two后,One才会被停止?

然后,我们再点back回到第一个界面,这时走的次序是:

 
  1. onPause(TWO) - onActivityResult(ONE) - onStart(ONE) -  onRestart(ONE) - onResume(ONE) - onStop(TWO) - onDestroy(TWO) 

说明,返回时,Two没有经历冻结就直接暂停了,在One接收参数,重启后,Two就停止并被销毁了。最后,我们点一下Exit退出应用,它的次序是:

 
  1. onPause(ONE) - onStop(ONE) - onDestroy(ONE) 

说明如果我们用了finish的话,不会有freeze,但是仍会经历pause - stop才被销毁。

这里有点疑问的是:为什么回来时先是Start才是Restart?可是文档中的图上画的却是先restart再start的啊?不过,后面的表格中的描述好象是正确的,start后面总是跟着resume(如果是第一次)或者restart(如果原来被stop掉了,这种情况会在start与resume 中插一个restart)。

标题SpringBoot智能在线预约挂号系统研究AI更换标题第1章引言介绍智能在线预约挂号系统的研究背景、意义、国内外研究现状及论文创新点。1.1研究背景与意义阐述智能在线预约挂号系统对提升医疗服务效率的重要性。1.2国内外研究现状分析国内外智能在线预约挂号系统的研究与应用情况。1.3研究方法及创新点概述本文采用的技术路线、研究方法及主要创新点。第2章相关理论总结智能在线预约挂号系统相关理论,包括系统架构、开发技术等。2.1系统架构设计理论介绍系统架构设计的基本原则和常用方法。2.2SpringBoot开发框架理论阐述SpringBoot框架的特点、优势及其在系统开发中的应用。2.3数据库设计与管理理论介绍数据库设计原则、数据模型及数据库管理系统。2.4网络安全与数据保护理论讨论网络安全威胁、数据保护技术及其在系统中的应用。第3章SpringBoot智能在线预约挂号系统设计详细介绍系统的设计方案,包括功能模块划分、数据库设计等。3.1系统功能模块设计划分系统功能模块,如用户管理、挂号管理、医生排班等。3.2数据库设计与实现设计数据库表结构,确定字段类型、主键及外键关系。3.3用户界面设计设计用户友好的界面,提升用户体验。3.4系统安全设计阐述系统安全策略,包括用户认证、数据加密等。第4章系统实现与测试介绍系统的实现过程,包括编码、测试及优化等。4.1系统编码实现采用SpringBoot框架进行系统编码实现。4.2系统测试方法介绍系统测试的方法、步骤及测试用例设计。4.3系统性能测试与分析对系统进行性能测试,分析测试结果并提出优化建议。4.4系统优化与改进根据测试结果对系统进行优化和改进,提升系统性能。第5章研究结果呈现系统实现后的效果,包括功能实现、性能提升等。5.1系统功能实现效果展示系统各功能模块的实现效果,如挂号成功界面等。5.2系统性能提升效果对比优化前后的系统性能
在金融行业中,对信用风险的判断是核心环节之一,其结果对机构的信贷政策和风险控制策略有直接影响。本文将围绕如何借助机器学习方法,尤其是Sklearn工具包,建立用于判断信用状况的预测系统。文中将涵盖逻辑回归、支持向量机等常见方法,并通过实际操作流程进行说明。 一、机器学习基本概念 机器学习属于人工智能的子领域,其基本理念是通过数据自动学习规律,而非依赖人工设定规则。在信贷分析中,该技术可用于挖掘历史数据中的潜在规律,进而对未来的信用表现进行预测。 二、Sklearn工具包概述 Sklearn(Scikit-learn)是Python语言中广泛使用的机器学习模块,提供多种数据处理和建模功能。它简化了数据清洗、特征提取、模型构建、验证与优化等流程,是数据科学项目中的常用工具。 三、逻辑回归模型 逻辑回归是一种常用于分类任务的线性模型,特别适用于二类问题。在信用评估中,该模型可用于判断借款人是否可能违约。其通过逻辑函数将输出映射为0到1之间的概率值,从而表示违约的可能性。 四、支持向量机模型 支持向量机是一种用于监督学习的算法,适用于数据维度高、样本量小的情况。在信用分析中,该方法能够通过寻找最佳分割面,区分违约与非违约客户。通过选用不同核函数,可应对复杂的非线性关系,提升预测精度。 五、数据预处理步骤 在建模前,需对原始数据进行清理与转换,包括处理缺失值、识别异常点、标准化数值、筛选有效特征等。对于信用评分,常见的输入变量包括收入水平、负债比例、信用历史记录、职业稳定性等。预处理有助于减少噪声干扰,增强模型的适应性。 六、模型构建与验证 借助Sklearn,可以将数据集划分为训练集和测试集,并通过交叉验证调整参数以提升模型性能。常用评估指标包括准确率、召回率、F1值以及AUC-ROC曲线。在处理不平衡数据时,更应关注模型的召回率与特异性。 七、集成学习方法 为提升模型预测能力,可采用集成策略,如结合多个模型的预测结果。这有助于降低单一模型的偏差与方差,增强整体预测的稳定性与准确性。 综上,基于机器学习的信用评估系统可通过Sklearn中的多种算法,结合合理的数据处理与模型优化,实现对借款人信用状况的精准判断。在实际应用中,需持续调整模型以适应市场变化,保障预测结果的长期有效性。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值