Android——Intent用法

Intent,意圖,一般可以被用於啓動活動、啓動服務以及發送廣播等場景,現在先說一下啓動活動這部分。

Intent分爲顯式Intent和隱式Intent。

一、顯式Intent的使用

Intent有多個構造函數的重載,常用的一個有Intent(Context packageContext, Class<?> cls)。這個構造函數需要接受兩個參數,第一個參數Context要求提供一個啓動活動的上下文,一般就是自身的活動類名,而第二個參數Class則是需要指定想要啓動的目標活動類名。

例子:

新建一個命名爲FirstActivity的活動,在其界面佈局中添加一個Button,現在需要實現點擊Button後跳轉到另一個活動:SecondActivity,那麼可以在FirstActivity中添加如下代碼

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.firstlayout);
    Button button1 = (Button) findViewById(R.id.button1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            startActivity(intent);
        }
    });
}

如以上例子,需要在點擊FirstActivity中的Button控件後跳轉到SecondActivity,這時就可以通過Intent(意圖)來實現。

註冊Button的點擊事件爲Intent。Intent構造方法中的第一個參數爲:FirstActivity.this,指的是需要啓動跳轉操作的是當前的活動;第二個參數爲:SecondActivity.class,指的是需要跳轉到的目標活動是SecondActivity。在構件好Intent後將該Intent對象傳入startActivity()方法即可啓動目標活動了。

二、隱式Intent的使用

相比顯示Intent,隱式Intent稍微複雜一點。隱式Intent需要指定action、category等信息,交由系統分析這個Intent,然後才能找到相應的活動去啓動。

首先,需要配置AndroidManifest.xml文件中<activity>標籤下<intent-filter>標籤的內容,可以指定當前活動能夠響應的action和category。

<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="MyApplication.intent.action.START" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.Mycategory" />
    </intent-filter>
</activity>

這裏的<action>標籤指明瞭當前活動可以響應的action爲MyApplication.intent.action.START,而<category>標籤則包含了一些附加信息,可以更精確地指明當前活動能響應的Intent中還可能帶有的category。

然後,修改需要通過Intent來啓動該活動的FirstActivity中按鈕的點擊事件:

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.setAction("MyApplication.intent.action.START");
        //Intent intent = new Intent("MyApplication.intent.action.START");//設置Action另一種更加便捷的寫法
        //intent.addCategory("android.intent.category.DEFAULT");//這句省略也行,省略時在startActivity時會自動添加
        intent.addCategory("android.intent.Mycategory");
        startActivity(intent);
    }
});

每個Intent只能指定一個action,但是可以指定多個category,只有當<action>和<category>中的內容和Intent中指定的action和category的內容一致時,這個活動才能響應Intent。

要注意的是,Activity中的intent.addCategory("android.intent.category.DEFAULT")可以省略不寫,因爲在startActivity方法運行的時候系統會自動添加這句,但是在AndroidManifest中的<Activity>中

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

是不可以省略的,因爲在運行startActivity方法時,如果沒有顯示寫intent.addCategory("android.intent.category.DEFAULT")這句,系統一定會自動添加,所以如果<Activity>中省略了

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

那麼系統會找不到對應相匹配的活動來啓動,從而報錯:

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=MyApplication.intent.action.START cat=[android.intent.Mycategory] }

(也就是說在設置<Activity>中的<action>標籤時,<category android:name="android.intent.category.DEFAULT" />必須配套出現)

三、隱式Intent其他用法

隱式Intent還可以用來調用系統瀏覽器來展示頁面、調用撥號程序、打開地圖定位等。

在Activity中添加按鈕控件,修改Activity中按鈕的點擊事件:

//調用系統默認瀏覽器打開網頁
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
	//Uri傳值第一種方法
        Intent intent = new Intent(Intent.ACTION_VIEW);
 intent.setData(Uri.parse("https://www.baidu.com"));
        startActivity(intent);
    }
});

//調用撥號程序
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v) {
	//Uri傳值第二種方法
        Uri uri = Uri.parse("tel:10086");
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        startActivity(intent);
    }
});

//打開地圖定位
Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("geo:39.868433,116.013426"));
        startActivity(intent);
    }
});

首先我們指定了Intent的Action爲Intent.ACTION_VIEW,這是一個Android系統內置的動作,其常量值爲android.intent.action.VIEW。然後通過Uri.parse()方法,將一段字符串解析成一個Uri對象,並將其通過setData方法傳遞給Intent(代碼中的方法一,方法二則是通過Intent的構造方法直接將Uri對象傳遞進去)

四、向下一個活動傳遞數據

Intent還可以在啓動活動的時候傳遞數據:我們可以通過Intent中提供的putExtra()方法,將我們想要傳遞的數據暫時存儲在Intent中,並在另一個活動啓動後,再從Intent中取出來。

示例:

在FirstActivity中需要將一個字符串傳遞給SecondActivity。

首先修改FirstActivity中的按鈕點擊事件

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String data = "I am FirstAvtivity";
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        intent.putExtra("key",data);
        startActivity(intent);
    }
});

這裏的putExtra()方法接收了兩個參數,第一個爲鍵名,第二個纔是想要傳遞的數據。SecondActivity需要通過鍵名取出FirstActivity從Intent傳遞過來的數據。

SecondActivity:

public class SecondActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.secondlayout);
        Intent intent = getIntent();
        String data = intent.getStringExtra("key");
        Log.d("SecondActivity", data);
    }
}

在SecondActivity中,首先通過getIntent()方法獲取到用於啓動SecondActivity的Intent,然後使用intent.getStringExtra()方法來獲取鍵名爲key的數據(由於傳遞的數據爲String類型,所以使用的是getStringExtra()方法,若數據爲整形類型和布爾類型,則相應地使用getIntExtra()方法和getBooleanExtra()方法)。

在運行FirstActivity後,點擊button1按鈕,跳轉到了SecondActivity,查看logcat,可以看到SecondActivity成功取得了FirstActivity中傳遞過來的信息。

五、返回數據給上一個活動

數據可以從上一個活動流向下一個活動,那麼如果需要下一個活動給予上一個活動一個反饋的數據呢?這時候就需要用到startActivityForResult()方法了。查看文檔可以知道startActivityForResult()方法也是用於啓動活動的,但這個方法能夠在活動銷燬時返回一個結果給上一個活動。

startActivityForResult()接收兩個參數,第一個參數是Intent,第二個參數是請求碼,請求碼用於判斷數據來源,因此必須具有唯一性。

示例:現在需要實現退出SecondActivity後SecondActivity給FirstActivity回傳一個數據。

首先修改FirstActivity中button1點擊事件,不使用startActivity而是使用startActivityForResult()方法來啓動SecondActivity,同時傳入一個唯一的請求碼1。

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        startActivityForResult(intent,1);
    }
});

然後修改SecondActivity中button2的點擊事件,添加傳遞數據的邏輯。

Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.putExtra("data_result", "I am SecondAcitivity");
        setResult(RESULT_OK, intent);
        finish();
    }
});

從代碼中可以看出,SecondActivity新建了一個Intent用於傳遞數據,同時也使用了一個setResult的方法,該方法接收了Intent對象,可以推測數據的傳遞就是通過該方法來進行的。

setResult()方法接收兩個參數,第一個參數一般用於反饋當前活動對數據的處理結果,一般使用RESULT_OK或者RESULT_CANCELED這兩個值,第二個參數則爲需要傳遞的數據。

由於我們使用了startActivityForResult()方法來啓動SecondActivity,與此對應的,在SecondActivity被銷燬後會回調上一個活動的onActivityResult()方法,因此我們還需要在FirstActivity中重寫該方法來獲取數據。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case 1:
            if (resultCode == RESULT_OK) {
                String returnedData = data.getStringExtra("data_result");
                Log.i("FirstActivity", returnedData);
            }
            break;
        default:
    }
}

onActivityResult()方法接收三個參數,第一個requestCode就是我們在通過startActivityForResult()方法啓動活動的時候傳入的唯一的請求碼,在該方法中會根據這個請求碼進行相應的邏輯處理;第二個參數resultCode就是我們在返回數據時調用的setResult()方法傳入的處理結果;第三個參數則爲用於傳遞數據的Intent對象。

在啓動FirstActivity後先點擊button1啓動SecondActivity,再點擊button2,銷燬SecondActivity,返回到FirstActivity,看logcat打印

SecondActivity的數據成功傳遞迴FirstActivity。

需要注意的是,這是通過點擊Activity中的按鈕進行對SecondActivity進行銷燬的方法,若用戶沒有點擊該按鈕,而是點擊手機中的返回鍵,那麼這時數據就傳遞不回上一個活動了。

但是,我們可以通過在SecondActivity中重寫onBackPressed()方法來解決這個問題:

@Override
public void onBackPressed() {
    Intent intent = new Intent();
    intent.putExtra("data_result", "I am SecondAcitivity");
    setResult(RESULT_OK, intent);
    finish();
}

這時在SecondActivity中點擊Back鍵,logcat中依然會有打印,說明數據已成功傳遞到FirstActivity中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章