進階之路 | 奇妙的Activity之旅

前言

本文已經收錄到個人Github我的博客,歡迎大佬們光臨寒舍:html

個人GIthub博客java

本篇文章須要已經具有的知識:

  • Activity的基本概念
  • AndroidManifest.xml的基本概念

學習清單:

  • Activity的生命週期
  • Fragment的生命週期
  • Activity的啓動模式
  • IntentFilter的匹配規則

一.爲何要深刻了解Activity呢?

Activity翻譯爲活動,在Android中表明瞭界面和以界面爲中心相應的業務邏輯,包括顯示、與用戶交互等,它也是四大組件之一,重要性不言而喻。而且,許多公司在考察Android的知識點的時候,常常會考察到Activity的知識。android

所以,深刻了解Activity,不只對你平常的開發有幫助,還對你以後找工做有所增益。git

二.核心知識點概括

2.1 生命週期全解析

2.1.1 典型狀況下的生命週期

2.1.1.1 Activity生命週期圖解

活動生命週期圖

2.1.1.2 Activity切換過程

(1)啓動Activitygithub

啓動Activity

(2)打開新的Activity / 切換到桌面緩存

  • 正常狀況:onPause()-->onStop()
  • 特殊狀況:當新的Activity使用了透明主題,當前的Activity不會回調onStop,會停留在Paused

想要了解Android 透明主題的能夠點擊連接:Android透明主題app

(3)返回舊的Activityide

  • 當舊的Activity不可見:post

    當舊的Activity不可見

  • 當舊的Activity可見:學習

當舊的Activity可見

問題思考:當前Activity爲A,打開新的ActivityB,那麼B的onResume()和A的onPause()的執行順序是怎樣的呢?

答案:AonPause()-->BonResume(),要獲得這個答案,須要對Activity的工做原理有所瞭解,筆者在本系列文章的後面幾篇會介紹。

小Tips:要關閉Activity的時候,儘可能在onStop()中進行耗時操做,而使得新Activity儘快顯示出來。

2.1.2 異常狀況下的生命週期

2.1.2.1 異常狀況下數據的保存和恢復

這個涉及到onSaveInstanceStateonRestoreInstanceState方法,具體可見下圖

數據恢復順序

須要特別留意的是:

  • onSaveInstanceState的執行順序,是在onStop以前,與onPause沒有既定順序
  • onRestoreInstanceState的執行順序,是在onStart以後

Q1:其中保存和恢復View的工做流程是怎樣的呢?

保存View的工做流程

能夠看出,保存和恢復View的工做流程是典型的委託思想,上層委託下層,父容器委託子元素處理事情。

後面會講到的View的繪製流程,事件分發機制等,都是纔有相似的思想。

Q2:其中數據恢復的方式有哪些?

  1. 在onCreate中恢復

    須要注意的是,必需要判斷Bundle是否爲空

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //方法一:在onCreate中調用緩存恢復數據,必需要判斷savedInstanceState是否爲空
            if (savedInstanceState != null) {
                String test = savedInstanceState.getString("extra_test");
                Log.d(TAG, "[onCreate]restore extra_test:" + test);
            }
        }
    
    複製代碼
  2. 在onRestoreInstanceState中恢復

    Bundle必定有值,不須要判斷是否爲空,是官方推薦的恢復數據的方法

    //利用onRestoreInstanceState 
    @Override
        protected void onRestoreInstanceState(Bundle savedInstanceState) {
            super.onRestoreInstanceState(savedInstanceState);
          
            String test = savedInstanceState.getString("extra_test");
            Log.d(TAG, "[onRestoreInstanceState]restore extra_test:" + test);
        }
    複製代碼
2.1.2.2 系統配置變化致使的異常

Q1:發生改變的系統配置一般有哪些?

  • locale:通常指切換了系統語言
  • orientation:旋轉屏幕
  • keyboardHidden:鍵盤的可訪問性發生變化,好比:調出鍵盤

Q2:想系統配置改變後,activity不被從新建立,應該怎麼辦?

ActivityManifest.xml中,對應的ActivityconfigChanges屬性中指定該選項

<activity android:name="com.ryg.chapter_1.MainActivity" android:configChanges="orientation|screenSize" android:label="@string/app_name" android:launchMode="standard" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
複製代碼
2.1.2.3 資源內存不足致使的異常

這種狀況應該很容易理解,類比於:當使用小內存手機的時候,會發現某些應用常常一切換後臺,就會自動關閉了,原理也是資源內存不足,被系統自動回收了。

Q1:Activity的優先級排序是什麼?

由上到下,優先級由高到低

  • 前臺Activity--正在和用戶交互
  • 可見非前臺Activity--好比說,彈出新的對話框,對話框後面的Activity即屬於可見非前臺Activity
  • 後臺Activity--已經被中止的Activity

Q2:怎麼提升後臺工做的優先級呢?

將後臺工做放入Service中,保證進程有必定的優先級

2.1.3 Fragment的生命週期

由於本篇是Activity篇,筆者不便大費周章地敘述,爲了知足求知慾強的讀者,筆者特意推薦一篇:Fragment生命週期,裏面寫得很是詳細


2.2 Activity啓動模式

2.2.1 Activity的四種啓動模式

a:standard:標準模式

  • 含義:每次啓動一個Activity就會建立一個新的實例,而無論實例存在與否。
  • 注意:使用ApplicationContext去啓動standard模式Activity就會報錯。由於standard模式的Activity會默認進入啓動它所屬的任務棧,可是因爲非Activity的Context沒有所謂的任務棧,因此就會報錯。

b:singleTop:棧頂複用模式

  • 含義:若是新Activity已經位於任務棧的棧頂,就不會從新建立,並回調**onNewIntent(intent)**方法。

c:singleTask:棧內複用模式

  • 含義:只要Activity在一個棧中存在,都不會從新建立,並回調onNewIntent(intent)方法。若是不存在,系統會先尋找是否存在須要的棧,若是不存在該棧,就建立一個任務棧,並把該Activity放進去;若是存在,就會查看棧中是否有實例存在,若實例存在,則將實例調到棧頂,並回調onNewIntent(intent)方法,不然建立實例到已經存在的棧中。

d:singleInstance:單實例模式

  • 含義: 具備此模式的Activity只能單獨位於一個任務棧中,且此任務棧中只有惟一一個實例。

標識Activity任務棧名稱的屬性:android:taskAffinity,默認爲應用包名。

2.2.2 Activity的Flags

Flags有不少,這裏介紹幾個經常使用的Flags

  • FLAG_ACTIVITY_NEW_TASK:指定singleTask模式
  • FLAG_ACTIVITY_SINGLE_TOP:指定singleTop模式
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:指定新的Activity不會出如今最近啓動的Activity的列表中

2.3 IntentFilter的匹配規則

原則:

  • 一個intent只有同時匹配某個Activity的intent-filter中的actioncategorydata纔算徹底匹配,才能啓動該Activity。
  • 一個Activity能夠有多個intent-filter,一個 intent只要成功匹配任意一組 intent-filter,就能夠啓動該Activity。

Q1:action的匹配規則

  • 只要Intent中的存在一個action且可以和任何一個 intent-filter中的action相同便可成功匹配
  • 區分大小寫
  • 必須存在

Q2:category的匹配規則

  • 有其餘category,則要求intent中的category和intent-filter中的全部category 相同。
  • 非必須,這是由於此時系統給該Activity 默認加上了< category android:name="android.intent.category.DEAFAULT" />屬性值。

Q3:data匹配規則

  • 相似於action
  • URI非必須指定,默認值爲contentfile

須要注意的是,爲Intent指定完整的data的時候,要調用setDataAndType(URI,mimeType)方法

intent.setDataAndType(Uri.parse("file://abc"),"video/png");
複製代碼

採用隱式方式啓動Activity時,能夠用PackageManagerresolveActivity(Intent)方法或者IntentresolveActivity(Intent)方法,來判斷是否有Activity匹配該隱式Intent,若是匹配不到,會返回NULL

三.課堂小測試

恭喜你,已經看完了前面的文章,相信你對Activity已經有必定深度的瞭解,下面,進行一下課堂小測試,驗證一下本身的學習成果吧!

  • 題目情景:有三個Activity,分別名爲A,B,CA的啓動模式是standardBC的啓動模式是singleTask,如今進行以下操做:A啓動了B,B啓動了C,C啓動了A,A再啓動B,如今連按2次BACK,你看到的是哪一個Activity

  • 答案揭曉:回到桌面,具體過程能夠參考下面的流程圖

    流程圖


若是文章對您有一點幫助的話,但願您能點一下贊,您的點贊,是我前進的動力

本文參考連接:

相關文章
相關標籤/搜索