14天學會安卓開發(第二天)Android程式設計基礎activity和intent

查志強發表於2014-06-25

【原文:http://blog.csdn.net/corder_raine/article/details/8310114

14天學會安卓開發  
作者:神祕的N (英文名  corder_raine)
聯絡方式:369428455(反饋)
交流群:284552167(示例,原文件下載)


版權為作者所有,如有轉載請註明出處

目錄


第二天Android程式設計基礎... 31
2.1 深入瞭解安卓... 31

2.1.1 工程結構解析... 32
2.1.2 Android中JAVA包功能描述... 32
2.1.3 Android程式核心元件... 33

2.2 瞭解Activity. 33
2.2.1 Activity的概念... 33
2.2.2 Activity的生命週期

2.3 瞭解Intent 35
2.3.1 什麼是意圖: 35

2.4 Bundle類的作用... 37

2.5 回顧helloandroid看看安卓程式是怎麼運作的... 37

2.6 寫第二個程式ActivityLifeCycle. 39

2.7 使用過濾器: 43



第二天Android程式設計基礎.
2.1 深入瞭解安卓
21.png

22.png 

2.1.1 工程結構解析
src:              Java原始碼目錄(只允許有一個包)
AndroidMainfest.xml      (清單檔案,描述應用程式構成、元件、許可權等配置資訊)
gen/R.java  資原始檔,修改後自動重新生成
Android   庫
assets:            靜態資產檔案(用於存放不編譯的資源最大支援1G)
drawable:       程式圖示(ico.png)
layout:           佈局資料夾
values:程式用到的string、顏色(string.xml)
classes.dex      編譯的java二進位制碼     Android平臺上的可執行檔案
ActivityLifeCycle.apk   Android安裝包(APK 包)
resources.ap_    資源資訊檔案

2.1.2 AndroidJAVA包功能描述
Ø  android.app :提供高層程式模型、提供基本的執行環境
Ø  android.content :對裝置上的資料進行訪問和釋出的類
Ø  android.database :通過內容提供者瀏覽和運算元據庫
Ø  android.graphics :底層的圖形庫
Ø  android.location :定位和相關服務的類
Ø  android.media :管理多種音訊、視訊的媒體介面
Ø  android.net :提供幫助網路訪問的類
Ø  android.os :提供了系統服務、訊息傳輸、IPC 機制
Ø  android.opengl :提供OpenGL 的工具
Ø  android.provider :提供類訪問Android內容提供者
Ø  android.telephony :提供與撥打電話相關的API互動
Ø  android.view :提供基礎的使用者介面介面框架
Ø  android.util :涉及工具性的方法,例如時間日期的操作
Ø  android.webkit :預設瀏覽器操作介面
Ø  android.widget :包含各種UI元素在應用程式的螢幕中使用





2.1.3 Android程式核心元件
View:                   介面檢視、組織UI控制元件
Intent:                   意圖,支援元件間通訊
Activity:                      處理介面與UI互動
Content Provider:  儲存共享資料
IntentReceiver:      接收資訊及事件處理
Service:                 後臺服務(如硬體與驅動的服務)
Notification:          訊息與通知


2.2 瞭解Activity
2.2.1 Activity的概念
Ø  活動是最基本的Android應用程式元件
Ø  一個活動通常就是一個單獨的螢幕,它將會顯示由檢視控制元件組成的使用者介面,並對事件做出響應以啟動其他元件。
Ø  當一個新的螢幕開啟後,前一個螢幕將會暫停,並儲存在歷史堆疊中。使用者可以返回到歷史堆疊中的前一個螢幕。當螢幕不再使用時,還可以從歷史堆疊中刪除。Android將會保留從主螢幕到每一個應用的執行螢幕。
Ø  所有應用的Activity都繼承於android.app.Activity 類

2.2.2 Activity的生命週期
void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy()



23.png 




Activity有三個狀態:
l  當它在螢幕前臺時(位於當前任務堆疊的頂部),它是啟用或執行狀態。它就是響應使用者操作的Activity。
l  當它失去焦點但仍然對使用者可見時(如右圖),它處於暫停狀態。即在它之上有另外一個Activity。這個Activity也許是透明的,或者沒有完全覆蓋全屏,所以被暫停的Activity仍對使用者可見。暫停的Activity仍然是存活狀態(它保留著所有的狀態和成員資訊並保持和視窗管理器的連線),但系統處於極低記憶體時仍然可以殺死這個Activity。
l  完全被另一個Activity覆蓋時則處於停止狀態。它仍然保留所有的狀態和成員資訊。然而對使用者是不可見的,所以它的視窗將被隱藏,如果其它地方需要記憶體,則系統經常會殺死這個Activity。
Activity從一種狀態轉變到另一種狀態時,會呼叫以下保護方法來通知這種變化:

這七個方法定義了Activity的完整生命週期。實現這些方法可以幫助我們監視其中的三個巢狀生命週期迴圈:
l   Activity的完整生命週期自第一次呼叫onCreate()開始,直至呼叫onDestroy()為止。Activity在onCreate()中設定所有“全域性”狀態以完成初始化,而在onDestroy()中釋放所有系統資源。例如,如果Activity有一個執行緒在後臺執行從網路上下載資料,它會在onCreate()建立執行緒,而在 onDestroy()銷燬執行緒。
l   Activity的可視生命週期自onStart()呼叫開始直到相應的onStop()呼叫結束。在此期間,使用者可以在螢幕上看到Activity,儘管它也許並不是位於前臺或者也不與使用者進行互動。在這兩個方法之間,我們可以保留用來向使用者顯示這個Activity所需的資源。例如,當使用者不再看見我們顯示的內容時,我們可以在onStart()中註冊一個BroadcastReceiver來監控會影響UI的變化,而在onStop()中來注消。onStart() 和 onStop() 方法可以隨著應用程式是否為使用者可見而被多次呼叫。
l   Activity的前臺生命週期自onResume()呼叫起,至相應的onPause()呼叫為止。在此期間,Activity位於前臺最上面並與使用者進行互動。Activity會經常在暫停和恢復之間進行狀態轉換——例如當裝置轉入休眠狀態或者有新的Activity啟動時,將呼叫onPause() 方法。當Activity獲得結果或者接收到新的Intent時會呼叫onResume() 方法。關於前臺生命週期迴圈的例子請見PPT下方備註欄。


(活動通俗來說就活動的可操縱的視窗)

2.3 瞭解Intent
2.3.1 什麼是意圖:
1.Android基本的設計理念是鼓勵減少元件間的耦合
2.Intent提供通用的訊息系統,它允許在元件與元件間傳遞Intent來執行動作和產生事件。
3.使用Intent可以啟用Android應用的三個核心元件:活動、服務和廣播接收器。
4.Intent可以劃分成顯式意圖和隱式意圖。
5.顯式意圖:呼叫Intent.setComponent()Intent.setClass()方法指定了元件名或類物件的Intent為顯式意圖,顯式意圖明確指定了Intent應該傳遞給哪個元件。
6.隱式意圖:沒有呼叫Intent.setComponent()Intent.setClass()方法指定元件名或類物件的Intent為隱式意圖。 Android會根據intent-filter中設定的動作(action)、類別(category)、資料(URI和資料型別)找到最合適的元件來處理這個意圖。Intent Filter(過濾器)其實就是用來匹配隱式Intent。想要接收使用startActivity()方法傳遞的隱式意圖的活動必須在它們的意圖過濾器中包含"android.intent.category.DEFAULT"


(簡單舉個例子,我意圖打劫,所以意圖就是那麼一回事)





24.png 







2.4 Bundle類的作用
Bundle類用作攜帶資料,它類似於Map,用於存放key-value名值對形式的值。相對於Map,它提供了各種常用型別的putXxx()/getXxx()方法,如:putString()/getString()和putInt()/getInt(),putXxx()用於往Bundle物件放入資料,getXxx()方法用於從Bundle物件裡獲取資料。Bundle的內部實際上是使用了HashMap<String, Object>型別的變數來存放putXxx()方法放入的值:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
publicfinal class Bundle implementsParcelable, Cloneable {
            ......
 Map<String, Object> mMap;
 publicBundle() {
       mMap = newHashMap<String, Object>();
        ......
 }
 publicvoid putString(String key, String value) {
      mMap.put(key, value);
 }
publicString getString(String key) {
       Object o = mMap.get(key);
        return(String) o;
        ........//型別轉換失敗後會返回null,這裡省略了型別轉換失敗後的處理程式碼
}
}

在呼叫Bundle物件的getXxx()方法時,方法內部會從該變數中獲取資料,然後對資料進行型別轉換,轉換成什麼型別由方法的Xxx決定,getXxx()方法會把轉換後的值返回。


2.5 回顧helloandroid 看看安卓程式是怎麼運作的


       為什麼到了這裡我們才講android應用是怎麼運作的呢?到了這裡我們已經初步瞭解activity,intent,Bundle!
首先我們知道java是從Main進入程式的,那麼android是怎樣進入程式的呢?細心的朋友或許已經知道了, AndroidManifest.xml,就是我們程式的入口了.2.1節裡面,有這樣的一幅圖
26.png 

包名是我們建立目錄的包名,包名下面是版本號,
<application>標籤裡註冊了圖示,標題名,還有activity,   @是標準格式,R裡邊會有唯一的一個ID,比如XML是用來佈局的,那麼在R裡則會生成一個對應的ID,
<intent-filter>標籤監聽器,監聽activity第一個開啟

27.png 
那麼我們就可以去看看MainActivity

28.png 
首先我們看看是不是有activityonCreate!上面說,不論如何都要先執行它,然後傳進來一個Bundle型別的值,然後又呼叫自身這個類!底層程式碼已經幫我們實現好了,我們只需要用就行了.然後setContentView是得到內容檢視,得到那個檢視呢?剛剛我們不是說了嗎,註冊一個XML就會有一個R.獲取到activity_main這個檢視
那麼我們來看看佈局檔案xml裡是什麼,

29.png 
裡面就一個文字框,字串是找strings裡邊的一個字串

30.png 
所以我們建立helloandroid的時候,看到的就是hello world!
在此我們瞭解完了android的運作過程,那麼我們來寫第二個程式吧!

2.6 寫第二個程式ActivityLifeCycle
按照建立helloandroid程式的方法建立一個activityLifeCycle的專案
然後點選包右鍵新建一個類


為應用新增新的Activity

第一步:新建一個繼承Activity的類,如:NewActivity
1
2
3
4
5
6
publicclass NewActivity extendsActivity {
    @Overrideprotected void onCreate(Bundle savedInstanceState) {
                   super.onCreate(savedInstanceState);
          //這裡可以使用setContentView(R.layout.xxx)顯示某個檢視....
     }
}

第二步:需要在功能清單AndroidManifest.xml檔案中新增進上面Activity配置程式碼(紅色部分):
01
02
03
04
05
06
07
08
09
10
      package=“com.lxt008"
      android:versionCode="1"
      android:versionName="1.0">
    <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
        .....
        <activityandroid:name=".NewActivity"android:label="新activity的頁面標題"/>
    </application>
    ...
</manifest>

android:name屬性值的前面加了一個點表示NewActivity是當前包com.lxt008下的類,如果類在應用的當前包下,可以省略點符號,如果類在應用的子包下必須加點,如:NewActivity類在com.lxt008.user包下可以這樣寫:<activity android:name=“.user.NewActivity“ />






這裡說明一下onCreate是怎麼弄出來的!

32.png 
33.png 

在前面打勾按下OK


開啟新的Activity,不傳遞引數
在一個Activity中可以使用系統提供的startActivity(Intent intent)方法開啟新的Activity,在開啟新的Activity前,你可以決定是否為新的Activity傳遞引數:

第一種:開啟新的Activity,不傳遞引數
01
02
03
04
05
06
07
08
09
10
11
12
13
publicclass MainActivity extendsActivity {
  @Overrideprotected void onCreate(Bundle savedInstanceState) {
        .......
        Button button =(Button) this.findViewById(R.id.button);
                  button.setOnClickListener(newView.OnClickListener(){
                //點選該按鈕會開啟一個新的Activity
                publicvoid onClick(View v) {
                                  //新建一個顯式意圖,第一個引數為當前Activity類物件
                //第二個引數為你要開啟的Activity類
                startActivity(newIntent(MainActivity.this, NewActivity.class));
        }});
         }
}



上面定義了一個按鈕,findViewById是根據ID找到檢視,R.id.button那麼你的XML是不是要新增一個按鈕啊?在最新版的ADT21中,我們可以輕鬆的佈局了,在ADT8中拖動控制元件還是很麻煩的
       學過java的都會問,為什麼不直接NEW一個按鈕啊,那麼麻煩,android這樣是為了降低耦合度,高內聚,低耦合.

35.png 
當讓你也可以再xml裡自己寫控制元件

我們再回過頭來看button. setOnClickListener(new OnClickListener(){ })

這裡的setOnClickListener是放置一個點選監聽器裡邊有new了一個內部類
為什麼要這樣寫?當讓你也可以不這樣寫,這樣寫是為了方便,學過java的應該都知道吧!你另外寫一個類,然後再呼叫它也可以.
實現OnClickListener介面自動實現onClick方法
36.png 
這句可以分開來寫
1
2
3
Intent intent=newIntent();
intent.setClass(MainActivity.this, NewActivity.class);
startActivity(intent);

剛剛我們學了意圖,意圖是活動之間傳遞資訊的信使,第一個引數是自身的一個活動,第二個是要轉過去的活動.


使用過濾器:
如何弄出LoCat

37.png 
快捷欄裡沒有的話到Other裡邊找

38.png 
       相信學過java的對輸出語句並不陌生,點選上面綠色的那個加號就是新增過濾器的,by log level 是日誌型別,如上圖右邊的箭頭,從上到下有所有日誌,捉蟲日誌,資訊日誌,警告日誌,錯誤日誌
設定syso過濾器
       Syso的記錄日誌我覺得沒那麼亂,容易看出來,單獨顯示出來的,all 是所有資訊
39.png 40.png 
(詳情請參考demo, ActivityLifeCycle)







開啟新的Activity,傳遞引數給它

第二種:開啟新的Activity,並傳遞若干個引數給它:
01
02
03
04
05
06
07
08
09
10
11
12
13
publicclass MainActivity extendsActivity {
  @Overrideprotected void onCreate(Bundle savedInstanceState) {
        .......
         button.setOnClickListener(newView.OnClickListener(){
               publicvoid onClick(View v) {
                 Intent intent = newIntent(MainActivity.this, NewActivity.class)
Bundle bundle = newBundle();//該類用作攜帶資料
bundle.putString("name","lxt008");
bundle.putInt("age",80);
intent.putExtras(bundle);//附帶上額外的資料
startActivity(intent);
        }}); }
}

在新的Activity中接收前面Activity傳遞過來的引數:
1
2
3
4
5
6
7
publicclass NewActivity extendsActivity {
            @Overrideprotected void onCreate(Bundle savedInstanceState) {
             ........       
             Bundle bundle = this.getIntent().getExtras();
             String name = bundle.getString("name");
                            intage = bundle.getInt("age");
            }}



得到新Activity關閉後返回的資料

如果你想在Activity中得到新開啟Activity 關閉後返回的資料,你需要使用系統提供的startActivityForResult(Intent intent, int requestCode)方法開啟新的Activity,新的Activity 關閉後會向前面的Activity 傳回資料,為了得到傳回的資料,你必須在前面的Activity中重寫onActivityResult(int requestCode, int resultCode, Intent data)方法:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
publicclass MainActivity extendsActivity {
      @Overrideprotected void onCreate(Bundle savedInstanceState) {
        .......
        Button button =(Button) this.findViewById(R.id.button);
                           button.setOnClickListener(newView.OnClickListener(){//點選該按鈕會開啟一個新的Activity
                publicvoid onClick(View v) {
                //第二個引數為請求碼,可以根據業務需求自己編號
                startActivityForResult (newIntent(MainActivity.this, NewActivity.class), 1);
        }});
         }
    //第一個引數為請求碼,即呼叫startActivityForResult()傳遞過去的值
    //第二個引數為結果碼,結果碼用於標識返回資料來自哪個新Activity
   @Overrideprotected void onActivityResult(intrequestCode, intresultCode, Intent data) {
        String result = data.getExtras().getString(“result”));//得到新Activity 關閉後返回的資料
    }
}


當新Activity關閉後,新Activity返回的資料通過Intent進行傳遞,android平臺會呼叫前面Activity 的onActivityResult()方法,把存放了返回資料的Intent作為第三個輸入引數傳入,在onActivityResult()方法中使用第三個輸入引數可以取出新Activity返回的資料。


使用startActivityForResult(Intent intent, int requestCode)方法開啟新的Activity,新Activity關閉前需要向前面的Activity返回資料需要使用系統提供的setResult(int resultCode, Intent data)方法實現:
01
02
03
04
05
06
07
08
09
10
11
12
publicclass NewActivity extendsActivity {
        @Overrideprotected void onCreate(Bundle savedInstanceState) {
                ......
                button.setOnClickListener(newView.OnClickListener(){
                publicvoid onClick(View v) {
                        Intent intent = newIntent();//資料是使用Intent返回
                        intent.putExtra(“result”, “success”);//把返回資料存入Intent
                         NewActivity.this.setResult(RESULT_OK, intent);//設定返回資料
                         NewActivity.this.finish();//關閉Activity
                }});
        }
}

setResult()方法的第一個引數值可以根據業務需要自己定義,上面程式碼中使用到的RESULT_OK是系統Activity類定義的一個常量,值為-1,程式碼片斷如下:
1
2
3
4
5
publicclass android.app.Activity extends......{
  publicstatic final int RESULT_CANCELED = 0;
  publicstatic final int RESULT_OK = -1;
  publicstatic final int RESULT_FIRST_USER = 1;
}



       請求碼的作用

使用startActivityForResult(Intent intent, int requestCode)方法開啟新的Activity,我們需要為startActivityForResult()方法傳入一個請求碼(第二個引數)。請求碼的值是根據業務需要由自已設定,用於標識請求來源。例如:一個Activity有兩個按鈕,點選這兩個按鈕都會開啟同一個Activity,不管是那個按鈕開啟新Activity,當這個新Activity關閉後,系統都會呼叫前面Activity的onActivityResult(int requestCode, int resultCode, Intent data)方法。在onActivityResult()方法如果需要知道新Activity是由那個按鈕開啟的,並且要做出相應的業務處理,這時可以這樣做:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
@Override
[/b]publicvoid onCreate(Bundle savedInstanceState) {
        ....
        button1.setOnClickListener(newView.OnClickListener(){
          publicvoid onClick(View v) {
                   startActivityForResult (newIntent(MainActivity.this, NewActivity.class),1);
           }});
        button2.setOnClickListener(newView.OnClickListener(){
          publicvoid onClick(View v) {
                   startActivityForResult (newIntent(MainActivity.this, NewActivity.class),2);
           }});
       @Overrideprotected void onActivityResult(intrequestCode, intresultCode, Intent data) {
               switch(requestCode){
                   case1:
                       //來自按鈕1的請求,作相應業務處理
                   case2:
                        //來自按鈕2的請求,作相應業務處理
                }
          }
}


結果碼的作用

在一個Activity中,可能會使用startActivityForResult()方法開啟多個不同的Activity處理不同的業務,當這些新Activity關閉後,系統都會呼叫前面Activity的onActivityResult(int requestCode, int resultCode, Intent data)方法。為了知道返回的資料來自於哪個新Activity,在onActivityResult()方法中可以這樣做(ResultActivity和NewActivity為要開啟的新Activity):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
publicclass ResultActivity extendsActivity {
       .....
       ResultActivity.this.setResult(1, intent);
       ResultActivity.this.finish();
}
publicclass NewActivity extendsActivity {
       ......
        NewActivity.this.setResult(2, intent);
        NewActivity.this.finish();
}
publicclass MainActivity extendsActivity { // 在該Activity會開啟ResultActivity和NewActivity
       @Overrideprotected void onActivityResult(intrequestCode, intresultCode, Intent data) {
               switch(resultCode){
                   case1:
                       // ResultActivity的返回資料
                   case2:
                       // NewActivity的返回資料
                }
          }
}



原始碼下載

相關文章