Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android編程入門 >> Android Activity的4種啟動模式詳解(示例)

Android Activity的4種啟動模式詳解(示例)

編輯:Android編程入門

轉載請注明出處:http://hovertree.com/

先介紹下Android對Activity的管理,Android采用Task來管理多個Activity,當我們啟動一個應用時,Android就會為之創建一個Task,然後啟動這個應用的入口Activity(即<intent-filter.../>中配置為 MAIN和LAUNCHER的Activity)。

因為Android並沒有為Task提供API,因此我們無法真正去訪問Task,只能調用Activity的getTaskId()方法來獲取它所在的Task的ID。事實上我們可以把Task理解成Activity棧,Task以棧的形式來管理Activity:先啟動的Activity被放在Task棧底,後啟動的Activity被放在Task棧頂。

那麼Activity的加載模式,就負責管理實例化、加載Activity的方式、並可以控制Activity與Task之間的關系。

Activity有4中啟動模式,分別為:standard,singleTop,singleTask,singleInstance。如果要使用這四種啟動模式,必須在manifest文件中<activity>標簽中的launchMode屬性配置,如:

<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="standard"
>

</activity>

standard

標准啟動模式,也是Android的默認啟動模式。在這種模式下啟動的activity可以被多次實例化,即在一個任務中可以存在多個activity實例,每個實例都會處理一個Intent對象。如果Activity A的啟動模式為standard,並且A已經啟動,在A中再次啟動Activity A,即調用startActivity(new Intent(this,A.class)),會在A的上面再次啟動一個A的實例,即當前的棧中的狀態為A-->A。

singleTop

如果一個以singleTop模式啟動的activity的實例已經存在於任務棧的棧頂,那麼再次啟動這個activity時,不會創建新的實例,而是重用位於棧頂的那個實例,並且會調用該實例的onNewIntent()方法將Intent對象傳遞到這個實例中。舉例來說,如果A的啟動模式為singleTop,並且A的一個實例已經存在於棧頂中,那麼再調用startActivity(new Intent(this,A.class))啟動A時,不會再創建A的實例,而是重用原來的實例,並且調用原來實例的onNewIntent()方法。這時任務棧中還是有一個A的實例。

如果以singleTop模式啟動的activity的一個實例已經存在於任務棧中,但是不在棧頂,那麼它的行為和standard模式相同,也會創建多個實例。

singleTask

官方文檔上稱,如果一個activity的啟動模式為singleTask,那麼系統總會在一個新的任務的最底部(root)啟動這個activity,並且被這個activity啟動的其它activity會和該activity同時存在於這個新任務中。如果系統中已經存在一個這樣的activity則會重用這個實例,並且調用它的onNewIntent()方法。即,這樣的一個activity在系統中只會存在一個實例。

但是這種說法並不准確,采用singleTask啟動目標Activity時,可分三種情況:

1、如果將要開啟的目標Activity不存在,系統將會創建目標Activity實例,並將它放入Task棧頂。

2、如果將要啟動的目標Activity已經位於Task棧頂,此時與singleTop模式的行為相同。

3、如果將要啟動的目標Activity已經存在、但沒有位於Task棧頂,系統將會把位於該Activity上面的所有Activity移出Task棧,從而使得目標Activity轉入棧頂。

下面通過實例說明:

兩個Activity,FirstActivity顯示文本框和按鈕,該按鈕用於啟動SecondActivity;SecondActivity顯示文本框和按鈕,該按鈕用於啟動FirstActivity。

public class FirstActivity extends Activity {
    TextView tv;
    Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        tv=(TextView) findViewById(R.id.tv);
        tv.setText("Activity為:"+this.toString()+",Task ID為:"+this.getTaskId());
        btn=(Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}
public class SecondActivity extends Activity {
    TextView tv;
    Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        
        tv=(TextView) findViewById(R.id.tv);
        tv.setText("Activity為:"+this.toString()+",Task ID為:"+this.getTaskId());
        btn=(Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(SecondActivity.this, FirstActivity.class);
                startActivity(intent);
            }
        });
    }
}

運行該實例,系統默認啟動FirstActivity,點擊該界面按鈕,系統以singgleTask模式打開SecondActivity ,此時Task棧中有兩個Activity(從底向上):FirstActivity-->SecondActivity.

點擊SecondActivity界面按鈕,系統以標准模式再次啟動FirstActivity,此時Task棧中有三個Activity(從底向上):FirstActivity-->SecondActivity-->FirstActivity.

在FirstActivity中再次點擊按鈕,系統以singleTask模式再次打開SecondActivity,系統會將位於SecondActivity上面的所有Activity移出,使得SecondActivity進入棧頂,此時Task棧中只有兩個Activity(從底向上):FirstActivity-->SecondActivity.

效果圖(依次):

 

  

singleInstance

總是在新的任務中開啟,並且這個新的任務中有且只有這一個實例,也就是說被該實例啟動的其他activity會自動運行於另一個任務中。當再次啟動該activity的實例時,會重用已存在的任務和實例。並且會調用這個實例的onNewIntent()方法,將Intent實例傳遞到該實例中。和singleTask相同,同一時刻在系統中只會存在一個這樣的Activity實例。

說明:

這種加載模式下,系統保證無論從哪個Task中啟動目標Activity,只會創建一個目標Activity實例,並會使用一個全新的Task棧來裝載該Activity實例。

當用singleInstance啟動目標Activity時,分兩種情況:
1、當將要啟動的目標Activity不存在,系統會先創建一個全新的Task、再創建目標Activity的實例,並將它加入新的Task的棧頂。

2、如果將要啟動的目標Activity已經存在,無論它位於哪個應用程序中,無論它位於哪個Task中,系統將會把該Activity所在的Task轉到前台,從而使用該Activity顯示出來。

采用該模式加載的Activity總是位於Task棧頂,所在Task只包含該Activity.

舉例說明:

點擊FirstActivity中按鈕,啟動SecondActivity。SecondActivity配置成singleInstance加載模式,export屬性配置成true---表明該Activity可被其它應用啟動。

public class FirstActivity extends Activity {
    TextView tv;
    Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        tv=(TextView) findViewById(R.id.tv);
        tv.setText("Activity為:"+this.toString()+",Task ID為:"+this.getTaskId());
        btn=(Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}
        <activity
            android:name=".SecondActivity"
            android:launchMode="singleInstance"
            android:exported="true" >
            <intent-filter>
                <!--知道該Activity能響應Action為指定字符串的Intent  -->
                <action android:name="joanna.yan.action.TEST_ACTION" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

系統啟動新的Task並用新的Task加載新創建的SecondActivity實例,SecondActivity總是位於棧頂。

效果圖:

 

另一個示例采用隱式Intent再次啟動該SecondActivity。

代碼:

public class OtherActivity extends Activity {
    TextView tv;
    Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        
        tv=(TextView) findViewById(R.id.tv);
        tv.setText("Activity為:"+this.toString()+",Task ID為:"+this.getTaskId());
        btn=(Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
Intent intent=new Intent();
                intent.setAction("joanna.yan.action.TEST_ACTION");
                startActivity(intent);
            }
        });
    }
}

單擊OtherActivity中的按鈕隱式啟動singleInstance模式的SecondActivity,如果前面一個示例還未退出,無論SecondActivity所在Task是否位於前台,系統將再次把SecondActivity所在Task轉入前台,從而將SecondActivity顯示出來。

效果圖:

 

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