1. 程式人生 > >Android教程 -04 啟動其它Activity,靜態工廠設計模式傳遞資料

Android教程 -04 啟動其它Activity,靜態工廠設計模式傳遞資料

意圖 Intent

一個應用程式肯定不只有一個介面,如何切換到其它介面,只時候就需要啟動其它的Activity。啟動Activity有多種方式。我在這簡單總結下:

學習開啟其它的Activity,首先需要了解意圖:
Intent是在不同元件中(比如兩個Activity)提供執行時繫結的物件。Intent代表一個應用”想去做什麼事”,你可以用它做各種各樣的任務,不過大部分的時候他們被用來啟動另一個Activity。

顯示意圖

這裡寫圖片描述

顯示意圖顧名思義, 其實就是把要開啟的Activity的名字赤裸裸的寫在程式碼中。
如下面程式碼就是要啟動Demo2Activity,當然肯定需要上下文(Context)這個上帝類。需要注意的是要啟動的activity必須要在清單檔案(AndroidManifest.xml)中進行配置。

        //  初始化Button控制元件
        button= (Button) findViewById(R.id.button);
        //  設定button的點選事件
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //  宣告Button的點選事件 跳轉到Demo2Activity
                //  引數1 上下文  引數2 跳轉Activity的位元組碼
Intent intent = new Intent(getApplicationContext(), Demo2Activity.class); startActivity(intent); } });

顯示意圖啟動Activity的速度略快,不過有些侷限性,只能開啟自己程式中的Activity

隱式意圖

  1. 相對於顯示意圖更加含蓄
  2. 需要指定當前Activity 能夠響應的action或category。

每個Activity要想能被開啟都需要在清單檔案(AndroidManifest.xml)中進行配置,當配置完成,程式部署到手機的時候,該Activity會加入到系統的列表中。在配置的時候,我們可以對activity進行一些描述(新增action或category),另一個Activity通過這些描述就可以開啟這個Activity。
參考下圖:
這裡寫圖片描述

程式碼如下

    <!--在清單檔案中描述Demo2Activity-->
    <activity
        android:name=".Demo2Activity"
        android:label="@string/title_activity_demo2" >
        <intent-filter>
            <action android:name="aaa.bbb.ccc" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
     //  初始化Button控制元件
       button = (Button) findViewById(R.id.button);
       //  設定button的點選事件
       button.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               //通過隱式意圖開啟activity
               Intent intent = new Intent();
               intent.setAction("aaa.bbb.ccc");
               intent.addCategory("android.intent.category.DEFAULT");
               startActivity(intent);
           }
       });

隱式意圖不僅可以開啟自己程式的Activity,還可以開啟其它程式的Activity,一般的原則是開啟自己程式的Activity多用顯示意圖。

隱式意圖的常見操作

撥打電話

    /**
     * 撥打電話
     */
    public void dail(View v){
        Intent intent=new Intent();
        intent.setAction(Intent.ACTION_CALL);
        intent.setData(Uri.parse("tel:1333333333"));
        startActivity(intent);
    }

開啟瀏覽器

    /**
     * 開啟瀏覽器
     */
    public void goToBrowser(View v){
        Intent intent=new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);
    }

分享文字

   /**
    * 分享
    */
   public void share(View v){
       Intent intent=new Intent();
       intent.setAction(Intent.ACTION_SEND);
       // 指定引數的型別
       intent.setType("text/plain"); // "image/png"
       // 設定要分享的文字
       intent.putExtra(Intent.EXTRA_TEXT,"於連林很帥");
       startActivity(intent);
   }

需要注意的是,如果想讓你的程式具備分享其他程式文字的功能,需要在你想要分享的Activity新增如下配置:

    <activity
         android:name=".MainActivity"
        >
         <intent-filter>
             <action android:name="android.intent.action.SEND" />
             <data android:mimeType="text/plain" />
             <category android:name="android.intent.category.DEFAULT" />
         </intent-filter>
     </activity>

這樣我們程式的MainActivity就具備分享文字的功能了。

Activity之間傳遞資料

Activity之間傳遞資料是很常見的操作,傳遞資料核心的方法就是通過Intent的putExtra方法傳遞,可以傳遞的型別包括八大基本型別,字串和實現Serializable或Parcelable介面的物件,也可以傳遞ArrayList集合(集合裡對型別有約束,允許的型別包括String,Parcelable)。
寫法和用map集合新增資料一樣, 需要用到key-value鍵值對。

我們以SendDataActivity和RDataActivity為例演示一下程式碼:

    //  SendDataActivity傳遞資料給RDataActivity
    public void sendData(View v){
        Intent intent=new Intent(this,RDataActivity.class);
         intent.putExtra("key","要傳遞的資料");
        // 開啟Activity
        startActivity(intent); 
    }

下面是RDataActivity接受資料:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rdata);
        // 獲取到開啟當前Activity的意圖
        Intent intent =getIntent(); 
        // Value就是我們接受的資料
        String  value=intent.getStringExtra("key");
        //...
    }

需要注意的是兩個Activity的key(就是程式碼中”key”) 必須保持一致。但是這種寫法有個潛在的問題。

靜態工廠設計模式傳遞資料

在實際開發的過程中,往往同時有多個程式設計師寫不同的Activity。經常會出現傳遞資料的Activity和接受資料的Activity不是一個程式設計師寫的。為了保持key統一,就需要兩個程式設計師之間進行溝通,這樣大大提高了程式的耦合性,程式變的不那麼容易維護。

安卓中的基本問題之一就是對鍵/值對的持有。因為bundle 需要鍵/值對,所以你總是需要一個key。然而問題是哪裡儲存這些key?

與其建立另一個類的物件,不如讓對應的類自己建立物件。

我們接下來修改一下RDataActivity的程式碼,新增一個靜態方法,其餘不用變。讓RDataActivity自己建立自己的Intent

    public static Intent newIntent(Context context,String value){
        Intent intent=new Intent(context,RDataActivity.class);
        intent.putExtra("key",value);
        return intent;
    }

呼叫者類無需知道intent以及key的任何事情。SendDataActivity只需告訴RDataActivity,”嘿,我需要一個帶有這個資料的intent”。就是這樣,RDataActivity會做完其它的事情。我們接下來修改下SendDataActivity的sendData方法

  public void sendData(View v){
       Intent intent=RDataActivity.newIntent(this,"value");
       startActivity(intent);  // 開啟RDataActivity
   }

這樣改完以後程式碼就變的容易維護了。

返回資料給之前的Activity

回傳資料

這時候就用到兩個核心的方法:
1. startActivityForResult()
2. onActivityResult()

開啟Activity要用startActivityForResult了,我們繼續把上面的程式碼改造下:

    //  SendDataActivity傳遞資料給RDataActivity
    public void sendData(View v){
         Intent intent=RDataActivity.newIntent(this,"value");
         // 修改開啟Activity的方法
        startActivityForResult(intent,0);  //引數2是 requestCode請求碼
    }

RDataActivity新增程式碼:

    // 退出按鈕點選事件, 點選退出
    public void exit(View v){
        Intent  intent=new Intent();
        intent.putExtra("result","resultData"); //回傳的資料
        setResult(0, intent); //引數1: resultCode 結果碼
        finish();  // 主動關閉當前Activity
    }

當RDataActivity退出的時候就會呼叫SendDataActivity的onActivityResult()方法

   @Override
   // requestCode 請求碼   resultCode結果碼  data傳遞的資料
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode==0&&data!=null){
            String result=data.getStringExtra("result");
            Toast.makeText(this,result,Toast.LENGTH_LONG).show();
        }
    }