Activity Review

Activity Review

參考資料

谷歌Activity參考文檔

任務(wù)與返回棧, 官方文檔的描述

Activity啟動(dòng)方式和Flag詳解

Activity完全解析

Activity高級(jí)篇:Home鍵與Back鍵

Activity概述

一個(gè)應(yīng)用通常由多個(gè)彼此松散聯(lián)系的 Activity 組成。 一般會(huì)指定應(yīng)用中的某個(gè) Activity 為“主”Activity,即首次啟動(dòng)應(yīng)用時(shí)呈現(xiàn)給用戶的那個(gè) Activity。 而且每個(gè) Activity 均可啟動(dòng)另一個(gè) Activity,以便執(zhí)行不同的操作。 每次新 Activity 啟動(dòng)時(shí),前一 Activity 便會(huì)停止,但系統(tǒng)會(huì)在堆棧(“返回棧”)中保留該 Activity。 當(dāng)新 Activity 啟動(dòng)時(shí),系統(tǒng)會(huì)將其推送到返回棧上,并取得用戶焦點(diǎn)。 返回棧遵循基本的“后進(jìn)先出”堆棧機(jī)制,因此,當(dāng)用戶完成當(dāng)前 Activity 并按“返回”按鈕時(shí),系統(tǒng)會(huì)從堆棧中將其彈出(并銷毀),然后恢復(fù)前一 Activity。

啟動(dòng)Activity

Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

隱式意圖

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

Intent 對(duì)象的真正價(jià)值所在 — 您可以創(chuàng)建一個(gè) Intent 對(duì)象,對(duì)您想執(zhí)行的操作進(jìn)行描述,系統(tǒng)會(huì)從其他應(yīng)用啟動(dòng)相應(yīng)的 Activity. <參考文檔>

表述:
如果您想允許用戶發(fā)送電子郵件,可以創(chuàng)建上面的實(shí)例 Intent

添加到 Intent 中的 EXTRA_EMAIL extra 是一個(gè)字符串?dāng)?shù)組,其中包含應(yīng)將電子郵件發(fā)送到的電子郵件地址。 當(dāng)電子郵件應(yīng)用響應(yīng)此 Intent 時(shí),它會(huì)讀取 extra 中提供的字符串?dāng)?shù)組,并將它們放入電子郵件撰寫窗體的“收件人”字段。 在這種情況下,電子郵件應(yīng)用的 Activity 啟動(dòng),并且當(dāng)用戶完成操作時(shí),您的 Activity 會(huì)恢復(fù)執(zhí)行。

Manifest.xml

<activity
    android: name="com.alex33.SecondActivity"
    android: icon="@drawable/cat"
    android: label="第二個(gè)Activity">

    <intent-filter>
        <action android:name="com.alex33.JumpToSecondActiviy"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

SecondActivity.java

Intent i = new Intent();
i.setAction("com.alex33.JumpToSecondActivity");
i.addCategory("android.intent.category.DEFAULT");
startActivity(intent);
通過(guò)隱式意圖可以不報(bào)樓類文件的情況下, 調(diào)用一個(gè)Activity

Activity幾種狀態(tài)

  1. Active(活動(dòng) | Active/Runing):當(dāng)Activity位于棧頂時(shí),它是可見,有焦點(diǎn)的前臺(tái)Activity,可以用來(lái)響應(yīng)用戶的輸入。

  2. Paused(暫停 | Paused):一般情況,你的Activity可見但不具有焦點(diǎn),例如 當(dāng)前面的Activity是全透明或非透明的Activity時(shí),下面的Activity就位于Paused狀態(tài)。

  3. Stopped(停止 | Stoped):當(dāng)一個(gè)Activity徹底不可見時(shí),就處于這個(gè)狀態(tài)。此時(shí)Activity完全不可見,但在內(nèi)存中仍舊保留該Activity的狀態(tài)和成員信息。

  4. Inactive(銷毀 | Killed):當(dāng)一個(gè)Activity被殺死時(shí),就變成Inactive。Inactive Activity會(huì)從Activity棧中移除,如果重新顯示需要重新啟動(dòng)。一般銷毀由系統(tǒng)Dalvik控制。

Activity加載模式

在android里,有4種activity的啟動(dòng)模式,分別為:

  1. standard: 標(biāo)準(zhǔn)模式,一調(diào)用startActivity()方法就會(huì)產(chǎn)生一個(gè)新的實(shí)例。

  2. singleTop: 來(lái)了intent, 每次都創(chuàng)建新的實(shí)例,僅一個(gè)例外:當(dāng)棧頂?shù)腶ctivity 恰恰就是該activity的實(shí)例(即需要?jiǎng)?chuàng)建的實(shí)例)時(shí),不再創(chuàng)建新實(shí)例。這解決了棧頂復(fù)用問(wèn)題。

  3. singleTask: 來(lái)了intent后,檢查棧中是否存在該activity的實(shí)例,如果存在就把intent發(fā)送給它,否則就創(chuàng)建一個(gè)新的該activity的實(shí)例,放入一個(gè)新的task棧的棧底??隙ㄎ挥谝粋€(gè)task的棧底,而且棧中只能有它一個(gè)該activity實(shí)例,但允許其他activity加入該棧。解決了在一個(gè)task中共享一個(gè)activity。

  4. singleInstance: 這個(gè)跟singleTask基本上是一樣,只有一個(gè)區(qū)別:在這個(gè)模式下的Activity實(shí)例所處的task中,只能有這個(gè)activity實(shí)例,不能有其他的實(shí)例。一旦該模式的activity的實(shí)例已經(jīng)存在于某個(gè)棧中,任何應(yīng)用在激活該activity時(shí)都會(huì)重用該棧中的實(shí)例,解決了多個(gè)task共享一個(gè)activity。
    這些啟動(dòng)模式可以在功能清單文件AndroidManifest.xml中進(jìn)行設(shè)置,中的launchMode屬性。

Activity 生命周期

Activity生命周期A
Activity生命周期Org
Activity生命周期Org

Activity跳轉(zhuǎn)時(shí)的方法回調(diào)

生命周期回調(diào)的順序經(jīng)過(guò)明確定義,當(dāng)兩個(gè) Activity 位于同一進(jìn)程,并且由一個(gè) Activity 啟動(dòng)另一個(gè) Activity 時(shí),其定義尤其明確。 以下是當(dāng) Activity A 啟動(dòng) Activity B 時(shí)一系列操作的發(fā)生順序:

  1. Activity A 的 onPause() 方法執(zhí)行。
  2. Activity B 的 onCreate()、onStart() 和 onResume() 方法依次執(zhí)行。(Activity B 現(xiàn)在具有用戶焦點(diǎn)。)
  3. 然后,如果 Activity A 在屏幕上不再可見,則其 onStop() 方法執(zhí)行。

您可以利用這種可預(yù)測(cè)的生命周期回調(diào)順序管理從一個(gè) Activity 到另一個(gè) Activity 的信息轉(zhuǎn)變。 例如,如果您必須在第一個(gè) Activity 停止時(shí)向數(shù)據(jù)庫(kù)寫入數(shù)據(jù),以便下一個(gè) Activity 能夠讀取該數(shù)據(jù),則應(yīng)在 onPause() 而不是 onStop() 執(zhí)行期間向數(shù)據(jù)庫(kù)寫入數(shù)據(jù)。

Manifest.xml的細(xì)節(jié)

清單文件中, intent過(guò)濾器有MAIN和LAUNCHER, 代表mainActivity的主入口

<intent-filter>  
    <action android:name = "android.intent.action.MAIN" />
    <category android:name = "android.intent.category.LAUNCHER" />  
</intent-filter>

使用Bundle在Activity間傳值

Bundle對(duì)象有如下方法:

  • putXxx(String key,Xxx data) : 向Bundle中放入int、String等各種類型的數(shù)據(jù)

  • putSerializable(String key,Serializable data) : 向Bundle中放入可序列化的對(duì)象

  • getXxx(String key):取出int、String等各種類型的數(shù)據(jù)

  • getSerializable(String key):取出可序列化的對(duì)象

當(dāng)然我們還可以直接調(diào)用intent對(duì)象的putExtra(String key,Xxx data)方法存入數(shù)據(jù),但其本質(zhì)還是創(chuàng)建或使用了Bundle對(duì)象進(jìn)行傳值。

startActivityForResult的使用

A-Activity需要在B-Activtiy中執(zhí)行一些數(shù)據(jù)操作,跳轉(zhuǎn)至B-Activity后,B-Activity要將執(zhí)行操作數(shù)據(jù)的結(jié)果返回給A-Activtiy,此時(shí)就需要使用 startActivityForResult()來(lái)啟動(dòng)B-Activity了。

使用的三個(gè)函數(shù):

  • startActivityForResult (Intent intent, Int requestCode)
  • setResut (int resultCode, Intent intent)
  • onActivityResult (int requestCode, int resultCode, Intent intent)

Step1.

在A中跳轉(zhuǎn)的時(shí)候不是采用startActivity(intent) 這個(gè)方法,而是startActivityForResult(intent, Int requestCode)的形式,requestCode可以是大于等于0的任何值。

startActivityForResult(intent, 0);

Step2.

在A中重寫onActivityResult方法,用來(lái)接收B回傳的數(shù)據(jù),因?yàn)閭骰貋?lái)的resultCode不同而做差別處理。

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    
    switch (resultCode) { //resultCode為回傳的標(biāo)記
        
        case 20:
            Bundle b=data.getExtras(); //data為B中回傳的Intent
            String str=b.getString("str1");//str即為回傳的值
            break;

        default:
            break;
    }
}

Step3.
在B中采用setResult方法,并且之后要調(diào)用finish方法。

Intent intent=new Intent();  
intent.putExtra("str1", str_bookname);  
setResult(20, data);  
finish(); //關(guān)閉掉這個(gè)Activity 

關(guān)于A-B Activity切換, Home鍵, Back鍵的機(jī)制

任務(wù)與返回棧, 官方文檔的描述

Activity 和任務(wù)的默認(rèn)行為總結(jié)如下:

  • 當(dāng) Activity A 啟動(dòng) Activity B 時(shí),Activity A 將會(huì)停止,但系統(tǒng)會(huì)保留其狀態(tài)(例如,滾動(dòng)位置和已輸入表單中的文本)。如果用戶在處于 Activity B 時(shí)按“返回”按鈕,則 Activity A 將恢復(fù)其狀態(tài),繼續(xù)執(zhí)行。

  • 用戶通過(guò)按“主頁(yè)”按鈕離開任務(wù)時(shí),當(dāng)前 Activity 將停止且其任務(wù)會(huì)進(jìn)入后臺(tái)。 系統(tǒng)將保留任務(wù)中每個(gè) Activity 的狀態(tài)。如果用戶稍后通過(guò)選擇開始任務(wù)的啟動(dòng)器圖標(biāo)來(lái)恢復(fù)任務(wù),則任務(wù)將出現(xiàn)在前臺(tái)并恢復(fù)執(zhí)行堆棧頂部的 Activity。

  • 如果用戶按“返回”按鈕,則當(dāng)前 Activity 會(huì)從堆棧彈出并被銷毀。 堆棧中的前一個(gè) Activity 恢復(fù)執(zhí)行。銷毀 Activity 時(shí),系統(tǒng)不會(huì)保留該 Activity 的狀態(tài)。
    即使來(lái)自其他任務(wù),Activity 也可以多次實(shí)例化。

Home鍵與Back鍵對(duì)Activity的生命周期影響

  • 如果按下Back鍵,系統(tǒng)返回到桌面,并依次執(zhí)行A:onPause -> A:onStop -> A:onDestroy。

  • 如果按下Home鍵(非長(zhǎng)按),系統(tǒng)返回到桌面,并依次執(zhí)行A:onPause -> A:onStop。

由此可見,Back鍵和Home鍵主要區(qū)別在于是否會(huì)執(zhí)行onDestroy。

Back鍵實(shí)現(xiàn)Home鍵效果

@Override
public void onBackPressed() {
    Intent home = new Intent(Intent.ACTION_MAIN);
    home.addCategory(Intent.CATEGORY_HOME);
    startActivity(home);
}

或者

@Override
public void onBackPressed() {
     moveTaskToBack(true);
} 

moveTaskToBack()此方法直接將當(dāng)前Activity所在的Task移到后臺(tái),同時(shí)保留activity順序和狀態(tài)。

關(guān)于finish()

  1. 將此Activity從Activity棧中移除。
  2. 調(diào)用了此Activity的onDestroy方法。

關(guān)于Activity的一些技巧

鎖定為豎屏

<activity android:name="com.alex33.MainActivity"
    android:label="@string/app_name" 
    android:screenOrientation="portrait">
        // 豎屏為portrait,橫屏為landscape
</activity>

去除標(biāo)題

requestWindowFeature(Window.FEATURE_NO_TITLE);

Android清單文件中MimeType的用途

Intent-Filter中的有一個(gè)mimeType。它的作用是告訴Android系統(tǒng)本Activity可以處理的文件的類型。如設(shè)置為 “text/plain”表示可以處理“.txt”文件。

<intent-filter>

    <actionandroid:name="android.intent.action.VIEW" />

    <categoryandroid:name="android.intent.category.DEFAULT" />

    <data android:mimeType="image/jpeg ">

</intent-filter>

這樣就把當(dāng)前程序注冊(cè)為可以打開/查看jpeg類型的圖片

當(dāng)在文件管理器里點(diǎn)擊任何jpeg文件, 系統(tǒng)都會(huì)試圖去執(zhí)行你的程序。

" image/jpeg "這一類型屬于標(biāo)準(zhǔn)的MIME Type。

一個(gè)簡(jiǎn)單的隱式跳轉(zhuǎn)并傳遞值的Demo

UI

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.goldinfo.sendmessage.MainActivity">

    <ListView
        android:id="@+id/ll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
</RelativeLayout>

item

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:text="TextView"
    android:id="@+id/textView"
    android:textColor="#123897"
    />

代碼實(shí)現(xiàn)

MainActivity

public class MainActivity extends AppCompatActivity {

    private ListView lv;


    private String[] msgs = {"天氣太熱了!買了個(gè)涼席,一睡變電熱毯了!遇到個(gè)陌生人,相視一笑,變熟了!桌子太燙,麻將剛碼好,嘿,居然糊了!",
            "工作是枯燥的,賺錢是辛苦的,理想?yún)s是遠(yuǎn)大的,等咱有了錢,喝豆?jié){吃油條,想沾白糖沾白糖,豆?jié){買兩碗,喝一碗,倒一碗!",
            "給你點(diǎn)陽(yáng)光你就燦爛,給你點(diǎn)洪水你就泛濫。破鍋?zhàn)杂衅棋伾w,丑鬼自有丑女愛(ài),只要情深意似海,麻子也能放光彩!",
            "鳥兒,鳥兒,喳喳叫。清風(fēng),清風(fēng),去煩惱。祝福,祝福要趁早。短信,短信,恰恰好。朋友,朋友,看到短信笑一笑!",
            "武當(dāng)派,少林派,不如吃個(gè)蘋果派;日月教,全真教,不如睡個(gè)大懶覺(jué);降龍掌,銷魂掌,不如養(yǎng)盆仙人掌;總之,你好我好大家好",
            "我的問(wèn)候,就是那冰激凌,融在你嘴里,甜在你胃里,爽在你心里。愿你把高溫?fù)敉?,把快?lè)放飛,生活有滋有味,笑容天天都美!",
            "送你西瓜,爽口爽心頂呱呱;送你電扇,吹走煩躁發(fā)發(fā)汗;送你清涼油,神清氣爽爭(zhēng)上游;送你清心茶,伴你天天樂(lè)開花!",
            "看事業(yè)線,你正走在成功路上;看生命線,你定會(huì)健康長(zhǎng)壽;看感情線,你桃花運(yùn)正旺。我的祝福三線合一,愿你快樂(lè)無(wú)比!",
            "送你五萬(wàn)塊,一萬(wàn)健康,一萬(wàn)快樂(lè),一萬(wàn)平安,一萬(wàn)好運(yùn),一萬(wàn)幸福,一共五萬(wàn)塊紅磚。嘿嘿,自己建造個(gè)美好城堡吧!",
            "好好活,慢慢過(guò),一年更比一年樂(lè);不要攀,不要比,不要自己氣自己;少吃鹽,多吃醋,少打麻將多散步。愿你:天天閑里忙著樂(lè)!"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = (ListView) findViewById(R.id.ll);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.item, msgs);

        lv.setAdapter(adapter);

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                //去除點(diǎn)擊條目的數(shù)據(jù)
                String content = msgs[position];

                //使用隱式意圖 跳轉(zhuǎn)到短信頁(yè)面
                Intent intent = new Intent();
                intent.setAction("android.intent.action.SEND");
                intent.addCategory("android.intent.category.DEFAULT");
                intent.setType("text/plain");

                //key值需要到android源碼中找
                intent.putExtra("sms_body",content);

                //開啟Activity
                startActivity(intent);


            }
        });

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

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

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