安卓藝術開發探索-----學習筆記(生命周期和啟動模式)
標簽: android
Activity的聲明周期和啟動模式
正常情況下,activity會經歷上圖的過程:
onCreate():表示activity正在被創建,這是生命周期的第一個方法。在這個方法中,我們可以做一些初始化,比如setContentView去加載界面資源,初始化activity所需要的數據
onStart():表示activity正在被啟動,這個時候activity已經可見了,但是還沒有出現在前臺,所以不能和用戶進行交互。這個可以理解為,activity已經可見了,但是我們看不見
onResume():表示activity已經可見了,并且出現在前臺并開始活動。
和onStart()的區別:onStart和onResume都表示activity已經可見了,但是onStart的時候,activity在后臺,onResume()的時候,activity才顯示在前臺
onPause():表示activity正在停止,正常情況下,onStop會緊接著被調用。在特殊情況下,如果在這個時候,重新返回activity,那么又會調用onResume。如果是新的activity被啟動,那么要圓activity的onPause執行完后,新activity的activity得出onResume()才會執行,所以一般不要在onPause()中執行太耗時的操作
onStop():表示activity即將停止,可以做一些回收工作,注意不要太耗時
onDestroy():表示activity即將被銷毀。這是activity生命周期的最后一個回調,我們可以在這里做一些資源的回收和釋放
onRestart():表示Activity正在被重啟。一般情況下,當activity從不可見變成可見的時候,onRestart就會被調用。這種一般出現在用戶用Home鍵切換到桌面或者打開一個新的activity
注意:
當用戶打卡新的activity或者切換到桌面的時候。回調是onPause->onStop,但是如果新的activity采用了透明主題,那么當前的activity不會回調onStop
當用戶按back鍵回退的時候,回調是onPause->onStop->onDestroy
onStart和onStop是從activity是否可見來回調的
onResume和onPause是從activity是否位于前臺來回調的
我們來看注意中的第一句話:
我做了一個小測試,我現在有兩個activity,一個MainActivity和SecondActivity,MAinActivity中聲明一個Button,用來轉到第二個activity
兩個activity都是用了透明主題
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button)findViewById(R.id.btn)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(
new Intent(MainActivity.this,SecondActivity.class));
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d("1111","onStart");
}
@Override
protected void onPause() {
super.onPause();
Log.d("1111","onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d("1111","onStop");
}
}
這是它的UI
第二個Activity沒有指定背景
當我跳轉到第二個activity的時候,就這樣了:
第一個activity還是可以看見,這是因為我采用的是透明主題,當我跳轉到第二個activity的時候,一個activity沒有執行onStop方法,只執行了onPause方法,導致我的第一個activity是可見的,但是出于后臺,不可操作
異常情況下的聲明周期
1,資源相關的系統配置發生改變導致Activity被殺死并重建
關于資源加載機制可以參考:
http://blog.csdn.net/thesingularityisnear/article/details/51581311
簡單說明一下,拿簡單的圖片來說,當我們放一張圖片在drawable目錄下,我們就可以用Resources去獲取這張照片。同時,我們為了兼容不同的設備,我們可能會在不同的目錄下放置不同的圖片,比如drawable—mdpi,drawable-hdpi,drawable-land等。這樣,當應用程序啟動的時候。系統會根據當前設備的情況去加載合適的Resources資源。
比如,當activity處于豎屏狀態的時候,如果突然選擇屏幕,由于系統配置發生了變化,在默認情況下,activity會銷毀然后重建,我們也可以阻止系統重建activity
注意:onSaveInstanceState方法的調用是在onStop之前,它和onPause沒有順序關系,可以在onPause之前也可以在之后,這個方法只會在activity被異常終止的情況下才會調用
從時序上說,onRestoreInstanceState的調用時機在onStart之后
關于保存和恢復View層次結構,系統dev工作流程是這樣的:
每一個View都有onSaveInstanceState和onRestoreInstanceState這兩個方法。
首先Activity被意外終止的時候,會調用onSaveInstanceState去保存數據,然后activity再去委托window去保存數據,接著window再委托它上面最頂層的容器去保存數據,頂層容器是一個ViewGroup,一般來說是一個DecorView。最后頂層元素再去通知它的子元素去保存數據
2,資源內存不足導致低優先級的activity被殺死
activity按照優先級從高到低,可以分為如下三種:
1)前臺activity—–正在和用戶交互的activity,優先級最高
2)可見但非前臺activity,比如activity中彈出一個對話框,導致activity可見但是位于后臺無法和用戶直接交互
3)后臺activity,已經被暫停的activity,比如執行了stop,優先級最低
當系統內存不足的時候,會按照上面的優先級去殺死activity所在的進程。
如果一個進程中沒有四大組件,那么這個進程很容易被殺死,所以一些后臺工作可以放在Service中
如果我們不想Activity重建,那么我們可以給activity指定configChanges屬性。比如不想activity在屏幕旋轉的時候重新創建,就可以給configChanges屬性添加orientation這個值
如果想使用多個值,可以用|來連接
當給configChanges設置屬性的時候,如果activity關于這個屬性的系統配置發生改變后,activity不會重新創建,所以也不會調用onSaveInstanceState和onRestoreSaveInstanceState方法,而是會去調用onConfigurationChanged方法,這個時候我們就可以在里面做一些操作。
Activity的啟動模式
- standard:標準模式,也是系統的模式模式。每次啟動一個Activity都會重新創建一個新的實例,不管這個實例是否已經存在。在這種模式下,誰啟動了這個Activity,那么這個Acivity鋸運行在啟動它的那個Activity所在的棧中。
- singleTop:棧頂復用模式。在這種模式下,如果新Activity已經位于任務棧的棧頂,那么此Activity不會被重新創建,同時它的onNewIntent方法會被回調,通過此方法的參數我們可以取出當前請求的信息。 需要注意的是,這個Activity的onCreate,onStart不會被系統調用,因為它并沒有發生改變。
如果新的Activity實例已存在但不是位于棧頂,那么新Activity仍然會重新創建。 - singleTask:棧內復用模式。這是一種單實例模式。這這種模式下,只要Activity在一個棧中存在,那么多次啟動此Activity都不會重新創建實例,和singleTop一樣,系統也會回調其onNewIntent。如果要啟動的Activity在此棧中有,就會將此Activity上面的其他Activity出棧,讓要顯示的位于棧頂
- singleInstance:單實例模式。這是一種加強的singleTask模式,它除了具有singleTask模式的所有特性外,還加強了一點,就是具有此模式的Activity安能單獨地位于一個任務棧中。只要這個Activity在棧中,由于棧內復用,后續的請求都不會創建新的Activity,除非這個棧被系統銷毀了
注意:
在singleTask中,在Acitity新建的時候,會尋找它所需要的任務棧。這里需要提到一個參數:TaskAffinity,任務相關性。這個參數標識了一個Activity所需要的任務棧的名字,在默認情況下,所有Activity所需要的任務棧的名字都為應用的包名。我們也可以為每個Activity單獨指定TaskAffinity屬性。
TaskAffinity與SingleTask配合使用的時候,它是具有該Activity目前任務棧的名字,待啟動的Activity會運行在名字和TaskAffinity相同的任務棧中
TaskAffinity與allowTaskReparenting結合的時候,它是表示兩個應用之間,如果應用A啟動了應用B的某個Activity,這個啟動的這個Activity的allowTaskReparenting為true的話,那么當應用B啟動后,這個Activity又會從應用A的任務棧轉移到應用B的任務棧(前面提過,A啟動B,B就在A的任務棧),這個時候,打開應用B看到的是被A啟動的Activity
另外,任務棧分為前臺任務棧和后臺任務棧
Activity的Flag
- FLAG_ACTIVITY_NEW_TASK:這個標志位的作用是為activity指定singleTask啟動模式,其效果和在XML中指定該模式相同
- FLAG_ACTIVITY_SINGLE_TOP:這個標志位的作用是為activity指定singTop啟動模式,其效果在和XML中指定該模式相同
- FLAG_ACTIVITY_CLEAR_TOP:具有此標志位的Activity,當它啟動的時候,在同一個任務棧中所有位于它上面的Activity都要出棧。這個模式一般和FLAG_ACTIVITTY_NEW_TASK配合使用,在這種情況下,被啟動的Activity的實例如果已經存在,那么系統就會調用它的onNewIntent方法。如果被啟動的Activity采用的是standard模式啟動,那么它連同它之上的Activity都要出棧,系統會創建新的Activity實例并放入棧頂
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有這個標志的Activity不會出現在歷史Activity的列表中,適用于不希望用戶通過歷史列表回到這個activity、它等同于在XML中指定Activity的屬性:android:excludeFromRecents = “true“
IntentFilter的匹配規則
啟動Activity分為顯示和隱式。在隱式調用中,需要Intent能夠匹配目標組件的IntentFilter中所設置的過濾信息,如果不匹配將無法啟動目標Activity。
IntentFilter中的過濾信息有action,category,data。
只有一個Intent同時匹配action類別,category類別,data類別才能算完全匹配,只有完全匹配才能成功啟動目標Activity。
一個Activity中可以有多個IntentFilter,只要一個Intent可以和其中的任何一個IntentFilter完全匹配,就可以啟動該Activity
1. action匹配規則:
action是一個字符串,系統預定義了一些action,同時我們也可以在應用中定義自己的action。一個IntentFilter中可以有多個action,只要Intent中的action能夠和過濾規則中任何一個action相同就算匹配成功。action區分大小寫
2. category匹配規則:
category是一個字符串,系統預定義了一些category,同時我們也可以在應用中自己定義category。如果Intent中含有category,那么多有的category必須和過濾規則中的其中一個category相同,也就是說Intent中含有的category必須在過濾規則中定義過。如果Intent中沒有category,系統會在啟動Activity的時候自動加上一個category:android:intent.category.DEFAULT。所以為了目標activity可以接收隱式調用,就應該在Intent-filter中指定“android.intent.category.DEFAULT”
3. data匹配規則:
data的語法:
data由兩部分組成,mimeType和URI。mimeType指媒體類型,比如image/jpeg,audio/mpeg4-geneic和video/*,可以表示圖片,文本,視頻等不同的媒體格式
URI的結構:
例子:
- Scheme:URI的模式,比如http,file,content等,如果URI中沒有指定scheme,那么整個URI的其他參數無效,也就意味著URI是無效的
- Host:URI的主機名,比如www.baidu.com,host必須指定
- Port,URI中的端口號,比如80,僅當URI中指定了Scheme和Host,port才有意義
- Path,pathPattern,和pathPrefix,這三個參數表示路徑信息,其中path表示完整信息,pathPattern也表示完整信息,但是它里面可以包含通配符“”,“”表示0個或者多個任意字符,需要注意的是,由于正則表達式的規范,如果想表示真實的字符串,那么“”要寫成“\”,“\”要寫成“\\”;pathPrefix表示路徑的前綴信息
data的匹配規則和action類似,Intent中必須要有data數據,并且data數據能夠完全匹配過濾規則中的某一個data。就是說過濾規則中出現的data部分也要出現在Intent中的data中
data的URI默認值為content和file
例子:
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.vivian.fighting"/>
<action android:name="com.vivian.world"/>
<category android:name="com.vivian.f1"/>
<category android:name="com.vivian.f2"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
-----
Intent intent = new Intent();
intent.setAction("com.vivian.fighting");
intent.addCategory("com.vivian.f1");
startActivity(intent);
一定要在Manifest中加
android:name="android.intent.category.DEFAULT"/>
,這表示這個Activity接受隱式調用,如果不加,就會出錯
將代碼改為:
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.vivian.fighting"/>
<action android:name="com.vivian.world"/>
<category android:name="com.vivian.f1"/>
<category android:name="com.vivian.f2"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"
android:scheme="file"
android:host="www.baidu.com"
/>
<data android:mimeType="image/jpeg"
android:scheme="file"
android:host="www.baidu.com"
/>
</intent-filter>
Intent intent = new Intent();
intent.setAction("com.vivian.fighting");
intent.addCategory("com.vivian.f1");
intent.setDataAndType(Uri.parse("file://www.baidu.com"),"text/plain");
startActivity(intent);
這樣可以啟動成功,根據實驗,其他就是在action,category,data匹配的時候,只要Intent中含有目標Activity匹配規則中的任何一個,都可以成功啟動
需要多說一點的是,action和data,系統給我們提供了很多action,可以讓我們去調用系統的東西,比如相冊,action是android.intent.action.GET_CONTENT
,data的mimeType是image/*
我們在做分享的時候,當我們要分享一些信息到其他應用,用的action是ACTION_SEND
,按需要設置data的mineType,如果有些應用要分享信息到該應用的某個activity,這個activity中的IntentFilter中的data要設置我們允許分享過來的mimeType
分享到其他App:
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT,"this is my text");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent,"Share to"));
分享到該App
<activity android:name=".ui.MyActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
智能推薦
Android開發藝術探索知識回顧——第1章 Activity的生命周期和啟動模式:2、啟動模式
1.2 Activity的啟動模式 上一節介紹了 Activity 在標準情況下和異常情況下的生命周期,我們對Activity的生命周期應該有了深入的了解。除了 Activity 的生命周期外,Activity 的啟動模式也是一個難點, 原因是形形色色的啟動模式和標志位實在是太容易被混淆了,但是Activity作為四大組件之首,它的的...
安卓學習筆記----淺析安卓生命周期
1. 簡述 安卓的生命周期有六個,分別為:onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy(),每一個Activity都有這些生命周期,通過這些生命周期,Activity在不存在,停止,暫停和運行之間轉換,如下圖: 2. 通過打印日志信息更深了解生命周期 如果對安卓Logcat工具或是日志打印不了解,請戳此鏈接 用到...
android開發藝術(一)之 Activity的生命周期和啟動模式
1.Activity的生命周期 一般分為兩部分,用戶參與下的典型情況生命周期,另一種是異常情況下的生命周期 1.1 典型情況下Activity生命周期 onCreate:表示Activity正在被創建,這是生命周期的第一個方法。 在這個方法中做初始化工作,比如調用setContentView去加載界面布局資源、初始化Activity所需數據等。此方法的傳參Bundle為該Activity上次被異常...
《Android開發藝術探索》Activity | 生命周期 | 啟動模式 | Flags | IntentFilter action data的匹配規則 (一)
說幾點 1.文章中大部分(所有吧)的內容都是與《Android開發藝術探索》書中寫的內容是一致的,所以可以說是直接copy了一遍(沒辦法,作者寫的太好了)。 2.為什么要copy一遍呢?,主要還是為了加深對知識的記憶和理解 不然只是匆匆忙忙的看了一遍,過后就啥都沒印象了。 3.記錄在博客里面,也是為了以后找起來更加的方便! 一:Activity的生命周期 正常情況下啟動一個Activity的生命周...
[AS 學習筆記] Activity生命周期和啟動模式
1. Activity的生命周期 Activity有四種生命狀態 ,分別是:running、paused、stopped、killed。 1.1 正常生命周期 onCreate(): 表示此時activity正在創建,通常進行一些初始化的方法。 onStart(): 表示此時activity已經被創建,但沒有位于前臺,處于可見但不可交互的狀態。 onResume(): 表示此時activity處于...
猜你喜歡
Android學習- Activity的生命周期和啟動模式
Activity 作者:桂志宏 Activity是Android四大組件之首,也是使用最為頻繁的組件,主要負責界面的顯示,因此Activity的重要性不言而喻。關于Activity的基本用法就不多說,下面主要討論兩個重要的過程:Activity的生命周期 和 Activity的啟動模式 Activity的生命周期 下面給出Activity生命周期的一張經典的流程圖 下面一一說明 onCreate:...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...