Android開發(fā) - Intent

什么是Intent

Intent是Android程序總各組件之間進(jìn)行交互的一種重要方式,它不僅可以指明當(dāng)前組件想要執(zhí)行的動作,還可以再不同組件之間傳遞數(shù)據(jù)。Intent一般可用于啟動活動、啟動服務(wù)以及發(fā)送廣播等場景。

Intent分類

  • 顯示Intent

Intent有很多構(gòu)造函數(shù)重載,其中一個是Intent(Context packageContext, Class<?>cls)。該函數(shù)接受兩個參數(shù),第一個參數(shù)是Context要求提供一個啟動活動的上下文,第二個參數(shù)Class則是指定想要啟動的目標(biāo)活動,通過這個構(gòu)造函數(shù)就可以創(chuàng)建出Intent的“意圖”。再使用startActivity()方法啟動活動,該方法接收一個Intent參數(shù),只需要將上邊創(chuàng)建好的Intent傳入該函數(shù)即可

創(chuàng)建兩個Activity,F(xiàn)irstActivity(主活動)和SecondActivity,在FirstActivity中創(chuàng)建一個按鈕,點擊之后進(jìn)入SecondActivity

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                // 構(gòu)建Intent,傳入FirstActivity.this作為上下文,傳入SecondActivity.class作為目標(biāo)活動
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                // 這樣"意圖"就比較明顯了,即在FirstActivity這個活動的基礎(chǔ)上打來SecondActivity這個活動,執(zhí)行Intent
                startActivity(intent);
            }
        });
    }

運行后就可以成功啟動SecondActivity了,如果想回到上一個活動,只要按下Back鍵就可以銷毀當(dāng)前活動,回到上一個活動了

  • 使用隱式Intent

相比于顯式Intent,隱式Intent并不明確指出想要啟動哪一個活動,而是指定一系列更為抽象的action和category等信息,然后交由系統(tǒng)去分析這個Intent,并找出合適的活動去啟動

那么什么是合適的活動呢?簡答來說就是可以響應(yīng)這個隱式Intent的活動。對于SecondActivity可以響應(yīng)什么樣的隱式Intent呢?通過在<activity>標(biāo)簽下配置<intent-filter>的內(nèi)容,可以指定當(dāng)前活動能夠響應(yīng)的action和category,打開AndroidMainfest.xml,添加如下代碼

<activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.znty.activitytest.ACTION_START" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

在<action>標(biāo)簽中,指明了當(dāng)前活動可以響應(yīng)com.znty.xietao.activitytest.ACTION_START這個action,而<category>標(biāo)簽則包含了一些附加信息,更明確地指明了當(dāng)前的活動能夠響應(yīng)的Intent中還可能帶有category。只有<action>和<category>中的內(nèi)容同時能夠匹配上Intent中指定的action和category時,這個活動才能響應(yīng)該Intent(就是起個名和分個類)。

回到FirstActivity中的按鈕事件,修改為:

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.znty.activitytest.ACTION_START");
                startActivity(intent);
            }
        });

可以看到使用了Intent的另外一個構(gòu)造函數(shù),直接將action的字符串傳進(jìn)去,表明想要啟動能夠響應(yīng)“com.znty.xietao.activitytest.ACTION_START”這個action的活動,由于category設(shè)置的是DEFAULT,這是一種默認(rèn)的category,在調(diào)用startActivity()方法的時候會自動將這個category添加到Intent中。

重新運行程序,可以得到和顯示Intent使用一樣的效果,這里使用的是隱式Intent,這就說明了在<activity>標(biāo)簽下設(shè)置的action和category的內(nèi)容生效了

每個Intent只能指定一個action,但卻能指定多個category。現(xiàn)在在Intent中除了默認(rèn)的category,再添加一個category。調(diào)用Intent的addcategory()方法來添加一個category

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.znty.activitytest.ACTION_START");
                intent.addCategory("com.zntq.activitytest.MY_CATEGORY");
                startActivity(intent);
            }
        });

同時需要在AndroidManifest.xml中進(jìn)行設(shè)置,否則的話整個程序就會直接閃退

<activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.znty.activitytest.ACTION_START" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="com.zntq.activitytest.MY_CATEGORY" />
            </intent-filter>
        </activity>

這樣再一次運行之后,就會發(fā)現(xiàn)一切都正常了

更多隱式Intent的用法

使用隱式Intent不僅可以啟動自己程序內(nèi)的活動,還可以啟動其他程序的活動,這使得Android多個應(yīng)用程序之間的功能共享成為了可能。比如在應(yīng)用程序中需要展示一個網(wǎng)頁,只需要調(diào)用系統(tǒng)的瀏覽器來打開這個網(wǎng)頁就行

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                // Intent.ACTION_VIEW是一個Android系統(tǒng)內(nèi)置的動作,它的常量值是"android.intent.action.VIEW"
                intent.setData(Uri.parse("http://www.baidu.com"));
                // 通過Uri.parse()方法,將一個網(wǎng)址字符串解析成一個UR對象,再調(diào)用Intent的setData()方法將這個Uri對象傳進(jìn)去
                // setData()方法,它接收一個Uri對象,主要用于指定當(dāng)前Intent正在操作的數(shù)據(jù),而這些數(shù)據(jù)通常都是以字符串的形式傳入到Uri.parse()方法中進(jìn)行解析產(chǎn)生的。
                startActivity(intent);
            }
        });

與上邊的對應(yīng),還可以再<intent-filter>標(biāo)簽中再配置一個<data>標(biāo)簽,用于更精確地指定當(dāng)前活動能夠響應(yīng)什么類型的數(shù)據(jù)。<data>標(biāo)簽中主要可以配置以下內(nèi)容

  • android:scheme。用于指定數(shù)據(jù)的協(xié)議部分,如上例中的http部分。
  • android:host。用于指定數(shù)據(jù)的主機(jī)名部分,如上例中的www.baidu.com部分。
  • android:port。用于指定數(shù)據(jù)的端口部分,一般緊隨在主機(jī)名之后。
  • android:path。用于指定主機(jī)名和端口之后的部分,如一段網(wǎng)址中跟在域名之后的部分。
  • android:mineType。用于指定可以處理的數(shù)據(jù)類型,允許使用通配符的方式進(jìn)行指定。

只有<data>標(biāo)簽中指定的內(nèi)容和Intent中攜帶的Data完全一致時,當(dāng)前活動才能夠響應(yīng)該Intent。不過<data>標(biāo)簽都不會指定過多的內(nèi)容,如上邊例子中,其實只需要指定android:scheme為http,就可以響應(yīng)所有的http協(xié)議的Intent了。

調(diào)用系統(tǒng)打電話功能,改變FirstActivity中按鈕想打電話的“意圖”,data部分指定的協(xié)議時10086,當(dāng)然還可以指定其他很多協(xié)議,如geo表示顯示地理位置等

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                // 響應(yīng)打電話功能
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:10086"));
                startActivity(intent);
            }
        });

向下一個Intent傳遞數(shù)據(jù)

Intent不僅能啟動Activity,還可以再啟動Activity的時候傳遞數(shù)據(jù)。它的思路很簡單,Intent提供了一系列putExtra()方法的重載,可以把想要傳遞的數(shù)據(jù)暫存在Intent中,啟動了另一個活動之后,只需要把這些數(shù)據(jù)再從Intent中取出來就可以了。

比如FirstActivity中有一個字符串,現(xiàn)在想把這個字符串傳遞到SecondActivity中,可以這樣編寫

在FirstActivity中:

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String data = "Hello SecondActivity";
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                intent.putExtra("extra_data", data); 
                // 第一個參數(shù)是鍵,用于后邊的取值,第二個參數(shù)是真正的數(shù)據(jù)
                startActivity(intent);
            }
        });

在SecondActivity中接收數(shù)據(jù):

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_layout);
        // 通過getIntent()方法獲取到用于SecondActivity的Intent
        Intent intent = getIntent();
        // 調(diào)用getStringExtra()方法來獲取傳遞的數(shù)據(jù),用鍵來取
        // 如果傳遞的是整型數(shù)據(jù),則使用getIntExtra()方法;傳遞的是布爾型數(shù)據(jù)getBoolExtra()方法
        String data = intent.getStringExtra("extra_data");
        System.out.println(data);
        Log.d("SecondActivity", data);
    }
}

返回數(shù)據(jù)給上一個Activity

返回上一個活動只需要按一下Back鍵就可以了,并沒有一個用于啟動活動Intent來傳遞數(shù)據(jù)。Activity還有一個startActivityForResult()方法也適用于啟動活動的,但是這個方法期望在活動銷毀的時候能夠返回一個結(jié)果給上一個活動,這就是我們所需要的。

startActivityForResult()方法接收兩個參數(shù),第一個參數(shù)還是Intent,第二個參數(shù)是請求碼,用于之后的回調(diào)中判斷數(shù)據(jù)的來源

修改FirstActivity中按鈕的點擊事件

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                // 使用startActivityForResult()方法來啟動Activity,請求碼只要是一個唯一值就可以了,這里傳入1
                startActivityForResult(intent, 1);
            }
        });

在SecondActivity中給按鈕注冊事件

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_layout);
        // 給按鈕注冊點擊事件,并在點擊事件中添加返回數(shù)據(jù)的邏輯
        Button button2 = (Button)findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 創(chuàng)建一個Intent,該Intent僅僅用于傳遞數(shù)據(jù),沒有指定任何的"意圖"
                Intent intent = new Intent();
                // 把數(shù)據(jù)存放在Intent中
                intent.putExtra("data_return", "Hello FirstActivity");
                // 調(diào)用setresult()方法,該方法是專門用于向上一個頁面?zhèn)鬟f數(shù)據(jù)的。接收兩個參數(shù),第一個參數(shù)
                // 用于向上一個活動返回處理結(jié)果,一般只使用RESULT_OK或RESULT_CANCELED這兩個值,第二個參數(shù)則把
                // 帶有數(shù)據(jù)的Intent傳遞回去
                setResult(RESULT_OK, intent);
                // 調(diào)用finish()方法來銷毀當(dāng)前活動
                finish();
            }
        });
    }

在SecondActivity銷毀之后會回調(diào)上一個活動的onActivityResult()方法,再回到FirstActivity

// 由于使用 startActivityForResult()方法來啟動SecondActivity的,在SecondActivity被銷毀之后會回調(diào)
    // 上一個活動也就是FirstActivity的onActivityResult()方法,因此重寫該方法
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // 該方法接收三個參數(shù),第一個參數(shù)requestCode,就是啟動活動時傳入的請求碼,第二個參數(shù)resultCode,即返回數(shù)據(jù)時
        // 傳入的處理結(jié)果,第三個參數(shù)就是攜帶者返回數(shù)據(jù)的Intent
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case 1:
                if (resultCode == RESULT_OK) {
                    String returnedData = data.getStringExtra("data_return");
                    Log.d("FirstActivity", returnedData);
                }
                break;
            default:
        }
    }

由于在一個Activity中有可能調(diào)用startActivityForResult()方法去啟動很多不同的Activity,每一個Activity返回的數(shù)據(jù)都會回調(diào)到onActivityResult()這個方法中,因此首先要通過檢查requestCode的值來判斷數(shù)據(jù)源。確定數(shù)據(jù)是從SecondActivity返回的之后,再通過resultCode的值來判斷處理結(jié)果是否成功,最后從data中取值并打印,這樣就完成了向上一個Activity返回數(shù)據(jù)的工作。

如果用戶在SecondActivity中并不是通過點擊按鈕而是通過按下Back鍵回到FirstActivity,這時候需要在SecondActivity中重寫onBackPressed()方法來解決:

@Override
    public void onBackPressed() {
        super.onBackPressed();
        Intent intent = new Intent();
        intent.putExtra("data_return", "Hello FirstActivity");
        setResult(RESULT_OK, intent);
        finish();
    }

這樣當(dāng)用戶按下Back鍵,就會執(zhí)行onBackPressed()方法中的代碼,從而在這里添加返回數(shù)據(jù)的邏輯就行。

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

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

  • 作為Android的四大組件之一,活動最先走進(jìn)我們的視野,其重要性不言而喻,今天就抽出時間來專門對Android活...
    loser先生閱讀 1,388評論 0 0
  • 如果一個 Intent 請求在一片數(shù)據(jù)上執(zhí)行一個動作, Android 如何知道哪個應(yīng)用程序(和組件)能用來響應(yīng)這...
    柒黍閱讀 5,979評論 0 1
  • 01. 你說,你愛我 可我卻忘了問 你愛的,是不是只有我 02. 分手那天,陽光明媚 可我的心 卻涼了一絲 03....
    一個喜歡深夜讀書的女子閱讀 666評論 4 21
  • 有這樣一種人 遇到一些傷心的事,想要去向朋友傾訴,于是用開玩笑的語氣跟她傾訴了,她會安慰我。 后來,遇到了已經(jīng)開不...
    聽你的聲音閱讀 179評論 0 0
  • 【引言】禪意隨心轉(zhuǎn),心在若有若無間輪轉(zhuǎn)流淌。像風(fēng)一樣似有似無,感覺得到卻抓不住。 【正文】 一個是皮囊 一個是靈魂...
    營州布衣閱讀 234評論 2 5

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