Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android基礎之四大組件---Activity

Android基礎之四大組件---Activity

編輯:關於Android編程

1.什麼是Activity?

Activity是用戶接口程序,它是Android應用程序的基本功能單元,它的主要功能是提供界面。Activity是Android的核心類,該類的全名是android.app.Activity。Activity相當於C/S程序中的窗體(From)或Web程序的頁面。每一個Activity提供一個可視化的區域。在這個區域可以放置各種Android組件,例如按鈕、圖像、文本框等。
  在Activity類中有一個oncreate事件方法,一般在該方法中對Acticity進行初始化。通過setContentView方法可以設置在Activity上顯示視圖組件。
  一個帶界面的Android應用程序可以由一個或者多個Activity組成。至於這些Activity如何工作,它們之間的依賴關系,則完全取決於應用程序間的業務邏輯。

2.Activity生命周期

在Activity建立到摧毀的過程中需要在不同的階段調用7個生命周期方法。這七個生命周期的定義如下:

    protected void onCreate(Bundle savedInstanceState) {} //在這裡創建界面,做一些數據的初始化工作;
    protected void onStart() {} //到這一步變成“用戶可見不可交互”的狀態;
    protected void onResume() {} //變成和用戶可交互的,(在Activity棧系統通過棧的方式管理這些Activity,即當前Activity在棧的最上端,運行完彈出棧,則回到上一個Activity);
    protected void onPause() {} //到這一步是可見但不可交互的,系統會停止動畫等消耗CPU的事情。從上文的描述已經知道,應該在這裡保存你的一些數據,因為這個時候你的程序的優先級降低,有可能被系統收回。在這裡保存的數據,應該在onResume裡讀出來。
    protected void onStop() {} //變得不可見 ,被下一個activity覆蓋了
    protected void onRestart() {}
    protected void onDestroy() {} //activity被消滅

  上面7個生命周期分別在4個階段按一定順序進行調用,

開始Activity:onCreate、onStart和onResume方法 Activity失去焦點:onPause和onStop方法 Activity重新獲得焦點:onRestart、onStart和onResume方法

關閉Activity:當Activity被關閉時系統會依次執行3個生命周期方法—onPause、onStop和onDestory方法

Activity的生命周期如下圖所示

這裡寫圖片描述

從圖中可以看出Activity包含兩層循環,第一層是onPause->onResume->onPause,第二層循環是onStop->onRestart->onStart->onResume->onPause->onStop。我們可以講兩層循環看成是整個Activity生命周期中的子生命周期。第一層成為焦點生命周期,第二層為可視生命周期。也就是說,第一層循環在Acitvity焦點的獲取與失去的過程中循環,這一過程中Activity是可見的。第二層循環實在Activity可見與不可見的過程中循環。
  因此,Activity有如下三種生命周期:

整體生命周期:onCreate->……->onDestroy.

可視生命周期:onStart->……->onStop. 焦點生命周期:onResume->onPause.

3.生命周期演示

示例代碼如下:

package com.hlh.activitydemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private static String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate: ");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: ");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: ");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: ");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: ");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, "onRestart: ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }
}

按如下步驟來操作應用程序:
(1)啟動應用程序
(2)按手機上的主頁按鈕進入主界面,然後重新進入應用程序界面
(3)關閉應用程序
按照上面步驟執行後,DDMS的Logcat打印的信息如下:
這裡寫圖片描述
從這個例子我們可以清晰看出Activity的整個生命周期的過程。

4.Activity之間的通信

在 Android 中,不同的 Activity 實例可能運行在一個進程中,也可能運行在不同的進程中。因此我們需要一種特別的機制幫助我們在 Activity 之間傳遞消息。Android 中通過 Intent 對象來表示一條消息,一個 Intent 對象不僅包含有這個消息的目的地,還可以包含消息的內容,這好比一封 Email,其中不僅應該包含收件地址,還可以包含具體的內容。對於一個 Intent 對象,消息“目的地”是必須的,而內容則是可選項。
  Intent負責對操作的動作、動作涉及數據、附加數據進行描述,Android則根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組件,並完成組件的調用。因此,Intent在這裡起著一個媒體中介的作用,專門提供組件互相調用的相關信息,實現調用者與被調用者之間的解耦。
  通過下面實例我們可以很好的了解Activity之間的通信,在主界面中點擊按鈕跳轉到另外一個activity,同時將數據傳遞給OtherActivity,綁定在TextView中。
  MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bt = (Button) findViewById(R.id.toOther);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, OtherActivity.class);
                intent.putExtra("msg", "hello Activity");
                startActivity(intent);
            }
        });
    }
}

OtherActivity.java

public class OtherActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other);
        TextView tv = (TextView) findViewById(R.id.tv);
        Intent intent = getIntent();
        //設置文本
        tv.setText(intent.getStringExtra("msg"));
    }
}

note:新建立了一個Actvity後,必須在AndroidManifest.xml清單文件中的標簽中注冊該actvity。

應用程序截圖:

 

這裡寫圖片描述
這裡寫圖片描述

5.Activity之加載模式

Activity有四種加載模式(launchMode)。launchMode在多個Activity跳轉的過程中扮演著重要的角色,它可以決定是否生成新的Activity實例,是否重用已經存在的實例,是否和其他Activity共用一個task。簡單介紹一個task,task是一個具有棧結構的對象,一個task可以管理多個Activity,啟動一個應用,也就創建一個與之對應的task。
  Activity的四種加載模式如下:
  1.standard
  2.singleTop
  3.singleTask
  4.singleInstance
  我們可以在AndroidManifest.xml配置的Android:launchMode屬性為以上四種之一即可。
  下面我們結合實例一一介紹這四種lanchMode:
  1.standard
  standard模式是默認的啟動方式,不用為配置android:launchMode屬性即可,當然也可以指定值為standard。我們創建一個Activity,命名為FirstActivity,來演示一下標准的啟動模式。FirstActivity代碼如下:

public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
        TextView textView = (TextView) findViewById(R.id.tv);
        textView.setText(this.toString());
        Button button = (Button) findViewById(R.id.start);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
                startActivity(intent);
            }
        });
    }
}

FirstActivity界面中的TextView用來顯示當前Activity實例的序列號,Button跳轉到下一個界面

連續點擊幾個Button按鈕,將會出現下面現象:

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

我們發現都是FirstActivity實例但是序列號不一樣,並且我們需要按兩次後退鍵才能返回到第一個  FirstActivity。每次跳轉系統都會在task中生成一個新的FirstActivity實例,並且將其放在棧頂,當我們按下back鍵時,才能看到原來的FirstActivity實例。

  因此總結出standard啟動模式,不管有沒有已經存在的實例,都會生成一個新的實例。 
  2.singleTop

我們在上面的基礎上為指定屬性android:launchMode=”singleTop”,系統就會按照singleTop啟動模式處理跳轉行為。我們重復上面幾個動作,將會出現下面的現象:

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

我們看到這個跟standard的結果不同,三個序列號都一樣,也就是說使用的是同一個FirstActivity實例。如果按back鍵,程序會立即退出。跳轉時系統會先在棧結構中尋找是否有一個FirstActivity實例正位於棧頂,如果有則不再生成新的,而是直接使用。也許有人會有疑問,我只看到棧內只有一個Activity,如果是多個Activity怎麼辦,如果不是在棧頂會如何?我們接下來再通過一個示例來證實一下大家的疑問。

再新建一個Activity命名為SecondActivity,代碼如下:

public class SecondActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        TextView tv = (TextView) findViewById(R.id.tv);
        tv.setText(this.toString());
        Button button = (Button) findViewById(R.id.start);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
                startActivity(intent);
            }
        });
    }
}

然後將之前的FirstActivity跳轉代碼改為:

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

演示結果如下:

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

我們看到,兩個FirstActivity的序列號是不同的,證明從SecondActivity跳轉到FirstActivity時生成了新的FirstActivity實例。

我們看到,當從SecondActivity跳轉到FirstActivity時,系統發現存在有FirstActivity實例,但不是位於棧頂,於是重新生成一個實例。

這就是singleTop啟動模式,如果發現有對應的Activity實例正位於棧頂,則重復利用,不再生成新的實例。

  3.singleTask

在上面的基礎上我們修改FirstActivity的屬性android:launchMode=”singleTask”。演示的結果如下:

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

我們注意到,在上面的過程中,FirstActivity的序列號是不變的,SecondActivity的序列號卻不是唯一的,說明從SecondActivity跳轉到FirstActivity時,沒有生成新的實例,但是從FirstActivity跳轉到SecondActivity時生成了新的實例。

在這個跳轉過程中系統發現有存在的FirstActivity實例,於是不再生成新的實例,而是根據棧先進後出的原則將FirstActivity之上的Activity實例統統出棧(如SecondActivity),將FirstActivity變為棧頂對象,顯示到幕前。如果將SecondActivity也設置為singleTask模式,那麼SecondActivity實例是不是可以唯一呢?在我們這個示例中是不可能的,因為每次從SecondActivity跳轉到FirstActivity時,SecondActivity實例都被迫出棧,下次等FirstActivity跳轉到SecondActivity時,找不到存在的SecondActivity實例,於是必須生成新的實例。但是如果我們有ThirdActivity,讓SecondActivity和ThirdActivity互相跳轉,那麼SecondActivity實例就可以保證唯一。

這就是singleTask模式,如果發現有對應的Activity實例,則使此Activity實例之上的其他Activity實例統統出棧,使此Activity實例成為棧頂對象,顯示到幕前。

  4.singleInstance
  這種啟動模式比較特殊,因為它會啟用一個新的棧結構,將Acitvity放置於這個新的棧結構中,並保證不再有其他Activity實例進入。
我們修改FirstActivity的launchMode=”standard”,SecondActivity的launchMode=”singleInstance”,由於涉及到了多個棧結構,我們需要在每個Activity中顯示當前棧結構的id,所以我們為每個Activity添加如下代碼:

TextView textView = (TextView) findViewById(R.id.tv);
textView.setText("current task id: " + this.getTaskId());

然後再演示一下這個流程:

 

這裡寫圖片描述

 

 

這裡寫圖片描述

 

我們發現這兩個Activity實例分別被放置在不同的棧結構中.可以發現從FirstActivity跳轉到SecondActivity時,重新啟用了一個新的棧結構,來放置SecondActivity實例,然後按下後退鍵,再次回到原始棧結構。

6.Activity的棧式管理

Android針對Activity的管理使用的是棧。你有可能不清楚什麼是棧,現在來解釋一下,棧是指數據項按序排列的數據結構,只能在一端(稱為棧頂(top))對數據項進行插入和刪除,一種先進後出的數據結構。而Android中是用task來存放Activity的。在第五小節簡單介紹了一下task。這裡詳細介紹一下
  google官網對task的定義:

A task is a collection of activities that users interact with when 
performing a certain job. The activities are arranged in a stack 
(the back stack), in the order in which each activity is opened.

  簡單來說task就是一組特定的activities集合,這些activities按照每一個被打開的順序放到一個stack(棧)中。Activity棧可以由一個或者多個Task組成。
  啟動一個應用時,系統會為之創建一個task來放置Activity,默認情況下,一個Activity啟動另外一個Activity時,兩個Activity放入同一個task中,後者被壓入前者所在的task棧中。當用戶按back鍵,後者從棧中彈出,前者又顯示在屏幕上。重點強調的是,啟動其他應用的Activity時,兩個Activity對用戶來說好像屬於同一個應用,其實這兩個Activity都創建了自己的task棧。系統中task和task之間是相互獨立的,當我們運行應用A時,按Home鍵回到主屏,啟動另外一個應用B,這時應用A的task被轉移到後台,剛啟動的應用B的task被轉移到前台,其棧頂Activity會顯示在屏幕上;再次按Home鍵回到開始啟動的應用A時,A應用的task任務棧又被轉移到前台,這時系統仍然保留task的所有Activity實例。
  
  

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved