1.Activity的創(chuàng)建
Activity 是Android 四大組件之一,用于展示界面
- Activity 中所有操作都與用戶密切相關(guān),是一個負(fù)責(zé)與用戶交互的組件,它上面可以顯示一些控件也可以監(jiān)聽并處理用戶的事件。
- 一個Activity 通常就是一個單獨(dú)的屏幕,Activity 之間通過Intent 進(jìn)行通信。
1.自定義類繼承Activity
新建一個Android 工程,在src 目錄下新建一個類,不妨起名MyActivity,讓該類繼承Android SDK提供的Activity。
2.MyActivity 中覆寫onCreate()方法
onCreate() 方法在當(dāng)前Activity 被系統(tǒng)創(chuàng)建的時候調(diào)用
- 在該方法中一般要通過setContentView(R.layout.myactivity)方法給當(dāng)前Activity 綁定布局文件或視圖。
- 因此為了讓我們的MyActivity能夠展示界面,需要在工程目錄的res/layout/目錄下創(chuàng)建一個布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="這是MyActivity的界面"/>
</LinearLayout>
3.AndroidManifest.xml 中進(jìn)行Activity 的注冊
Android 中共有四大組件,除了BroadCastReceiver 之外,其他三個組件如果要使用那么必須在AndroidManifest.xml 中進(jìn)行注冊(也叫聲明)
activity/android:name:要注冊的Activity 的全限定類名
activity/android:label:Activity 左上角顯示的名稱
intent-filter:叫意圖過濾器,一般用于隱式啟動該Activity
action/android:name:意圖過濾器的Action 名稱,可以自定義也可以使用系統(tǒng)提供的。
category/android:name:意圖過濾器的category 名稱,只能使用系統(tǒng)提供的常量值。
對于MainActivity來說正是配置了特定(action為android:name="android.intent.action.MAIN",category為android:name="android.intent.category.LAUNCHER")的intent-filter,那么當(dāng)應(yīng)用安裝好以后,才會在桌面創(chuàng)建一個圖標(biāo),點(diǎn)擊該圖標(biāo)打開MainActivity。
自定義的MyActivity如果也配置了一模一樣的intent-filter,那么系統(tǒng)也會為我的MyActivity 創(chuàng)建一個圖標(biāo),如果用戶點(diǎn)擊了該圖標(biāo),那么也可以直接打開我的MyActivity 界面。
也就是說一個Android 工程可以創(chuàng)建多個圖標(biāo),不過通常情況下一個Android 應(yīng)用只要給一個入口的Activity 配置為入口Activity 即可。
2.Activity的跳轉(zhuǎn)
顯式跳轉(zhuǎn):在可以引用到另外一個Activity 的字節(jié)碼,或者包名和類名的時候,通過字節(jié)碼,或者包名+類名的方法實(shí)現(xiàn)的跳轉(zhuǎn)叫做顯示跳轉(zhuǎn)。
顯示跳轉(zhuǎn)多用于自己工程內(nèi)部多個Activity 之間的跳轉(zhuǎn),因?yàn)樵谧约汗こ虄?nèi)部可以很方便地獲取到另外一個Activity 的字節(jié)碼。
隱式跳轉(zhuǎn):隱式跳轉(zhuǎn)不需要引用到另外一個Activity 的字節(jié)碼,或者包名+類名,只需要知道另外一個Activity 在AndroidManifest.xml 中配置的intent-filter 中的action 和category 即可。
言外之意,如果你想讓你的Activity 可以被隱式意圖的形式啟動起來,那么就必須為該Activity 配置intent-filter。
Activity 之間的跳轉(zhuǎn)都是通過Intent 進(jìn)行的。
Intent 即意圖,不僅用于描述一個Activity的信息,同時也是一個數(shù)據(jù)的載體。
顯示意圖
//通過Intent 的帶參構(gòu)造函數(shù)
Intent intent = new Intent();
//通過Intent 的setClass 方法
intent.setClass(this, SecondActivity.class);
//Intent 可以攜帶的數(shù)據(jù)類型
1.八種基本數(shù)據(jù)類型boolean、byte、char、short、int、float、double、long 和String 以及這9 種數(shù)據(jù)類型的數(shù)組形式
2.實(shí)現(xiàn)了Serializable 接口的對象
3.實(shí)現(xiàn)了Android 的Parcelable 接口的對象以及其數(shù)組對象
- 隱式意圖
//要跳轉(zhuǎn)的activity在清單文件里增在intent-filter
<intent-filter >
<action android:name="自己定義,習(xí)慣用包名后加功能名"/>
<category android:name="android.intent.category.DEFAULT"/> //默認(rèn)
</intent-filter>
//誰要跳轉(zhuǎn)到這個activity,誰的方法里面調(diào)用
Intent intent = new Intent();
intent.setAction("要跳轉(zhuǎn)的activity在清單文件里配置的action");
intent.addCategory("android.intent.category.DEFAULT");-->默認(rèn)
startActivity(intent);
- 隱示意圖需要注意的地方
在清單文件的 intent-filter 里面還可以配置 data標(biāo)簽,data標(biāo)簽可以配置多個不同種類型的
例如:
<data android:scheme="自己定義"/> -->設(shè)置前綴,與電話播放器調(diào)用很像
<data android:mimeType="text/plain"/> -->定義類型,這里不能隨意定義
在java代碼里,如果同時配置了scheme和mineType:
intent.setDataAndType(scheme,mimeType);
如果只配置scheme:
intent.setData();
如果只配置了mimeType:
intent.setType();
3.示例代碼
- 閃屏頁面
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(){
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Intent intent = new Intent();
intent.setClass(MainActivity.this, CalcActivity.class);
startActivity(intent);
finish();//把mainActivity關(guān)閉
}
}.start();
}
}
- 主頁面
public class ResultActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
// 獲取傳遞過來的Intent
Intent intent = getIntent();
// 取出對應(yīng)的數(shù)據(jù)
String name = intent.getStringExtra("name");
Bitmap bitmap = intent.getParcelableExtra("bitmap");
}
}
3.Activity 的生命周期
Activity 從創(chuàng)建到銷毀,整個生命周期是一個非常復(fù)雜的過程,該過程由Android 系統(tǒng)負(fù)責(zé)維護(hù)
1.Activity 的3種狀態(tài)
Resumed、Paused、Stopped可以理解為:激活或運(yùn)行狀態(tài)、暫停狀態(tài)、停止?fàn)顟B(tài)
Resumed 狀態(tài)
Activity 位于前端位置,并且獲取到了用戶的焦點(diǎn)。也就是當(dāng)前Activity 完全可見也可用。
注意:在Android 中目前只允許同時只能有一個Activity 位于前端位置。2.Paused 狀態(tài)
如果另外一個Activity 位于前端位置并且獲取了焦點(diǎn),但是該Activity 還依然可見,那么該Activity 就處于了Paused 狀態(tài)。
比如另外一個Activity 雖然位于前端,但是是透明的或者沒有占滿整個屏幕,那么就會出現(xiàn)上面的這種情況。
位于Paused 狀態(tài)的Activity 依然是“存活”著的,但是如果系統(tǒng)內(nèi)存極端的不足,那么就有可能被系統(tǒng)“殺死”以便釋放內(nèi)存。3.Stopped 狀態(tài)
當(dāng)另外一個Activity 完全將該Activity 遮蓋住的情況下,那么該Activity 就處于停止?fàn)顟B(tài)了。
位于停止?fàn)顟B(tài)的Activity 依然“活著”,但是它已經(jīng)對用戶完全不可見了,因此只要系統(tǒng)需要釋放內(nèi)存就會將該Activity“殺死”。
我們編寫的代碼要根據(jù)Activity 的不同狀態(tài)讓其做不同的工作。
如果我們的Activity 是用于播放視頻的:
當(dāng)其位于Resumed 狀態(tài)時我們可以讓視頻正常的播放。
當(dāng)Activity 位于Paused 狀態(tài)的時候,我們也應(yīng)該讓我們的視頻暫停播放。
當(dāng)Activity 位于Stopped 狀態(tài)時我們應(yīng)該停止播放視頻并釋放資源。
2.Activity 生命周期的回調(diào)方法
OnCreate
當(dāng)Activity 第一次創(chuàng)建時被調(diào)用,在該方法中我們應(yīng)該執(zhí)行創(chuàng)建視圖、初始化數(shù)據(jù)等工作。
該方法被調(diào)用之后緊接著就是調(diào)用onStart 方法。
onStart
當(dāng)Activity 對用戶可見前被系統(tǒng)調(diào)用。
onResume
當(dāng)Activity 可以跟用戶交互前被調(diào)用,該方法被調(diào)用后Activity 就處于Resumed 狀態(tài)。
onPause
當(dāng)另外一個Activity 即將成為Resumed 狀態(tài)前調(diào)用,在該方法中應(yīng)該保存臨時數(shù)據(jù)、停止動畫、暫停視頻播放器等。
必須要注意的就是該方法執(zhí)行必須要快,因?yàn)橹挥挟?dāng)該方法執(zhí)行過之后,另外一個Activity 才會成為Resumed 狀態(tài),不然會造成Activity 直接切換的“卡頓”現(xiàn)象。
onStop
當(dāng)Activity 對用戶已經(jīng)完全不可見的時候就會調(diào)用該方法。
當(dāng)另外一個Activity 已經(jīng)成為Resumed 狀態(tài)或者當(dāng)前Activity 被銷毀的情況下會導(dǎo)致當(dāng)前Activity 不可見。
onDestory
當(dāng)Activity 被銷毀前調(diào)用。
當(dāng)前Activity 調(diào)用finish()方法或者系統(tǒng)為了釋放內(nèi)存而將其銷毀都會調(diào)用該方法。
onRestart
當(dāng)Activity 處于onStop 狀態(tài)之后,如果重新啟動則會調(diào)用該方法。
比如如果當(dāng)前Activity位于Resumed 狀態(tài),此時我們按了Home 鍵,那么Activity 就完全不可見了,onStop 方法就會被執(zhí)行,然后再長按Home 鍵再將該Activity 重新啟動起來就會調(diào)用onRestart 方法。
3.橫豎屏切換時Activity 的生命周期
Android 手機(jī)在橫豎屏切換時,默認(rèn)情況下會把Activity 先銷毀再創(chuàng)建。
在類似手機(jī)游戲、手機(jī)影音這一類的應(yīng)用中,這個體驗(yàn)是非常差的。不讓Activity 在橫豎屏切換時銷毀,只需要在清單文件聲明Activity 時配置<activity>節(jié)點(diǎn)的幾個屬性即可,其方式如下:
//參數(shù)配置到Activity,就不會再銷毀和重新創(chuàng)建了
android:configChanges="orientation|keyboardHidden|screenSize"
//固定Activity 的方向
//有兩種方法:
//通過配置文件
在AndroidManifest.xml 中的activity 節(jié)點(diǎn)中添加如下屬性。
android:screenOrientation="portrait"
該屬性通常有兩個常量值,portrait:垂直方向,landscape:水平方向。
//通過代碼
在Activity 的onCreate 方法中執(zhí)行如下方法。
//垂直方向
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//水平方向
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
4.Activity 的啟動模式
1.Activity 的任務(wù)棧
Task Stack(任務(wù)棧)是一個具有棧結(jié)構(gòu)的容器,可以放置多個Activity 實(shí)例
- 數(shù)據(jù)結(jié)構(gòu):先進(jìn)后出
2.優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):提高了用戶體驗(yàn)
- 缺點(diǎn):
每開啟一次頁面都會在任務(wù)棧中添加一個Activity,而只有任務(wù)棧中的Activity 全部清除出棧時,任務(wù)棧被銷毀,程序才會退出,這樣的設(shè)計(jì)在某種程度上可能造成了用戶體驗(yàn)差,需要點(diǎn)擊多次返回才可以把程序退出了。
每開啟一次頁面都會在任務(wù)棧中添加一個Activity 還會造成數(shù)據(jù)冗余, 重復(fù)數(shù)據(jù)太多, 會導(dǎo)致內(nèi)存溢出的問題(OOM)。
3.啟動模式
Activity 的啟動模式
啟動模式(launchMode)在多個Activity跳轉(zhuǎn)的過程中扮演著重要的角色,它可以決定是否生成新的Activity 實(shí)例,是否重用已存在的Activity 實(shí)例,是否和其他Activity 實(shí)例共用一個task。
Activity 一共有以下四種啟動模式:standard、singleTop、singleTask、singleInstance。
我們可以在AndroidManifest.xml配置<activity>的android:launchMode屬性為以上四種之一即可。
standard: 標(biāo)準(zhǔn)啟動模式
特點(diǎn):默認(rèn)啟動模式, 每次激活A(yù)ctivity時(startActivity),都創(chuàng)建Activity實(shí)例,并放入任務(wù)棧singleTop:單一頂部模式
特點(diǎn):如果activity已經(jīng)被開啟,而且是在棧頂,就不會在創(chuàng)建當(dāng)前這個activity的實(shí)例,而是復(fù)用這個已經(jīng)開啟的activity,但是如果不是在棧頂,就會初始化一個新的實(shí)例,在整個棧里允許有多個實(shí)例singleTask:單一任務(wù)棧
特點(diǎn):當(dāng)前棧里只允許有一個當(dāng)前activity的實(shí)例,如果要開啟的activity在棧里存在,并且在底部,就會移除這個activity上面所有的activity
應(yīng)用場景:如果這個activity非常消耗cpu和內(nèi)存,建議把這個activity的啟動模式設(shè)置為singleTask,瀏覽器的browserActivity 設(shè)置的就是singleinstance:單一實(shí)例
特點(diǎn):整個手機(jī)操作系統(tǒng)只有一個實(shí)例,并且是單獨(dú)運(yùn)行在自己的任務(wù)棧里
應(yīng)用場景:通話界面的activity
Activity的啟動模式是很重要的一個知識點(diǎn),在項(xiàng)目開發(fā)中經(jīng)常會用到啟動模式來幫助我們解決一些比較難解決的bug,也可以幫助我們?nèi)?yōu)化一個項(xiàng)目的任務(wù)棧,防止界面太多導(dǎo)致卡頓和OOM。