Activity基礎(chǔ)知識

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。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容