Android四大組件之Activity

1. 什么是Activity

  • Activity負責UI元素的加載與頁面之前的跳轉(zhuǎn)箍邮,代表了一個頁面單元。

2. Activity的構(gòu)成

  • Activity的構(gòu)成并不是一個Activity對象再加上一個布局那么簡單叨叙,在Activity和開發(fā)人員設置的視圖之間還隔著兩層锭弊。
  • 實際上視圖會被設置給一個Window類,這個Window中含有一個DecorView擂错,這個DecorView才是整個窗口的頂級視圖味滞。開發(fā)人員設置的布局會被設置到這個DecorView的mContentParent布局中。
  • 也就是說Android中實際上內(nèi)置了一些系統(tǒng)布局文件xml钮呀,我們在xml中定義的視圖最終會被設置到這些系統(tǒng)布局的特定節(jié)點之下剑鞍,這樣就形成了整個的DecorView。

3. 隱式啟動Activity

  • 顯式Intent指的是Intent的“意圖”非常明顯爽醋,指明了從哪個活動跳轉(zhuǎn)到哪個活動蚁署。隱式Intent并不明確指出啟動哪一個活動,而是指定一系列更為抽象的action和category信息子房,然后交由系統(tǒng)去分析這個intent形用,并幫我們找到合適的活動去啟動就轧。

  • 默認的category的intent

  1. 創(chuàng)建FirstActivity,并且在配置文件中配置action和category:
public class FirstActivity extends Activity  {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/bt_first"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="I am FirstActivity"
        android:textSize="50px" />

</LinearLayout>
 <activity android:name=".FirstActivity">
        <intent-filter>
            <action android:name="com.fkq.menu.First" />
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
</activity>

說明:

  1. 在<action>標簽中我們指明了當前活動可以響應 com.fkq.menu.First 這個action田度,而<category>標簽則包含一些附加信息妒御,更精確地指明了當前的活動能夠響應的Intent中還可能帶有的category。
  2. 只有<action>和<category>中的內(nèi)容同時能夠匹配上Intent指定的action和category時镇饺,這個活動才能響應該Intent乎莉。

2.修改MainActivity,進行跳轉(zhuǎn):

    @InjectView(R.id.bt_main)
    Button btMain;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
        btMain.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                switch (view.getId()){
                    case R.id.bt_main:
                        startActivity(new Intent("com.fkq.menu.First"));
                }
            }
        });
    }

說明:android.intent.category.DEFAULT 是默認的category奸笤,在調(diào)用startActivity方法的時候會自動將這個category添加到Intent中惋啃。

  • 非默認的category的intent

每個Intent中只能指定一個action,但卻能指定多個category监右。

1.修改配置文件的category边灭,即添加一個:

<activity android:name=".FirstActivity">
            <intent-filter>
                <action android:name="com.fkq.menu.First" />
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="com.fkq.menu.my_category"/>
            </intent-filter>
</activity>

2.修改MainActivity的startActivity部分代碼:

Intent intent = new Intent("com.fkq.menu.First");
    intent.addCategory("com.fkq.menu.my_category");
    startActivity(intent);

4. 更多Intent用法

1. 簡單示例

使用隱式Intent,不僅可以啟動自己程序內(nèi)的活動健盒,還可以啟動其他程序的活動绒瘦,這使得Android多個應用程序之間的功能共享成為了可能。

比如應用程序中需要展示一個網(wǎng)頁扣癣,只需要調(diào)用系統(tǒng)的瀏覽器來打開這個網(wǎng)頁即可惰帽。

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);

說明:

  1. 首先指定了Intent的action是Intent.ACTION_ViEW,這是一個Android系統(tǒng)內(nèi)置的動作,其常量值為android.intent.action.VIEW.
  2. 然后通過Uri.parse方法父虑,將一個網(wǎng)址字符串解析承一個Uri對象该酗。
  3. 再調(diào)用Intent的setData方法將這個Uri對象傳遞進去。

再次說明:
setData方法接收一個Uri對象士嚎,主要用于指定當前Intent正在操作的數(shù)據(jù)呜魄,而這些數(shù)據(jù)通常都是以字符串的形式傳入到Uri.parse方法中解析產(chǎn)生的。

2. 配置data標簽

我們可以在<intent-filter>標簽中再配置一個<data>標簽莱衩,用于更精確地指定當前活動能夠響應什么類型的數(shù)據(jù)耕赘。<data>標簽中主要可以配置以下內(nèi)容:

  1. android:scheme 用于指定數(shù)據(jù)的協(xié)議部分,如上例中的http部分膳殷。
  2. android:host 用于指定數(shù)據(jù)的主機名部分,如上例中的www.baidu.com部分九火。
  3. android:port 用于指定數(shù)據(jù)的端口部分赚窃,一般緊跟在主機名之后。
  4. android:path 用于指定主機名和端口之后的部分岔激,如一段網(wǎng)址中跟在域名之后的內(nèi)容勒极。
  5. android:mimeType 用于指定可以處理的數(shù)據(jù)類型,允許使用通配符的方式進行指定虑鼎。

注意:只有<data>標簽中指定的內(nèi)容和Intent中攜帶的Data完全一致時辱匿,當前活動才能夠響應該Intent键痛。不過一般在<data>標簽中都不會指定過多的內(nèi)容,如上面瀏覽器示例中匾七,其實只需要指定android:scheme為http絮短,就可以響應所有的http協(xié)議的Intent了。

修改配置文件如下:

 <activity android:name=".FirstActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="http" />
        </intent-filter>
</activity>

說明:<data>標簽中通過android:sheme指定了數(shù)據(jù)的協(xié)議必須是http協(xié)議昨忆,這樣就和瀏覽器一樣丁频,能夠響應一個打開網(wǎng)頁的Intent了。

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);

除了http協(xié)議外邑贴,我們還可以指定很多其他協(xié)議席里,比如geo表示顯示地理位置、tel表示撥打電話拢驾。

<intent-filter>
    <action android:name="android.intent.action.DIAL" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="tel" />
</intent-filter>
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);

說明:

  1. 首先指定Intent的action是Intent.ACTION_DIAL,這又是Android系統(tǒng)的內(nèi)置動作奖磁。
  2. 然后在data部分指定了協(xié)議是tel,號碼是10086繁疤。

5. 向下一個活動傳遞數(shù)據(jù)

發(fā)送:

String data = "hello world";
Intent intent = new Intent(MainActivity.this,FirstActivity.class);
intent.putExtra("mydata",data);
startActivity(intent);

說明:通過putExtra方法傳遞一個字符串咖为,接收兩個參數(shù),第一個參數(shù)是鍵嵌洼,用于從Intent中取值案疲,第二個參數(shù)才是真正要傳遞的數(shù)據(jù)。

接收:

Intent intent = getIntent();
String data = intent.getStringExtra("mydata");
Toast.makeText(this, "傳遞過來的值是" + data, Toast.LENGTH_SHORT).show();

說明:通過getIntent方法獲取到用于啟動FirstActivity的Intent麻养,然后調(diào)用getStringExtra方法來獲取傳遞的數(shù)據(jù)褐啡。如果是整型數(shù)據(jù),則使用getIntExtra方法鳖昌,如果是布爾數(shù)據(jù)备畦,則使用getBooleanExtra方法。

6. 返回數(shù)據(jù)給上一個活動

Activity中有一個startActivityForResult方法用于啟動活動许昨,期望在活動銷毀的時候能夠返回一個結(jié)果給上一個活動懂盐。

  • 示例:MainActivity跳轉(zhuǎn)到FirstActivity,F(xiàn)irstActivity銷毀返回數(shù)據(jù)給MainActivity

MainActivity:

@Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.bt_trans:
                Intent intent = new Intent(MainActivity.this, FirstActivity.class);
                startActivityForResult(intent, 1);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode){
            case 1:
                if (resultCode == RESULT_OK){
                    String returnedData = data.getStringExtra("data_return");
                    Log.e("MainActivity",returnedData);
                }
        }
    }

說明:

  1. startActivityForResult方法接收兩個參數(shù)糕档,第一個參數(shù)還是intent莉恼,第二個參數(shù)是請求碼,用于在之后的回調(diào)中判斷數(shù)據(jù)的來源速那。
  2. 使用startActivityForResult方法啟動SecondActivity俐银,請求碼只要是唯一值就可以了,這里傳入了1端仰。

FirstActivity:

Button button = (Button) findViewById(R.id.bt_re_data);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                switch (view.getId()){
                    case R.id.bt_re_data:
                        Intent intent = new Intent();
                        intent.putExtra("data_return","hello");
                        setResult(RESULT_OK,intent);
                        finish();
                        break;
                }
            }
        });

說明:

  1. 在FirstActivity里面給按鈕添加點擊事件捶惜,并添加返回數(shù)據(jù)的邏輯。
  2. 構(gòu)建一個Intent僅僅用于傳遞數(shù)據(jù)而已荔烧,緊接著把要傳遞的數(shù)據(jù)存放在Intent中吱七,然后調(diào)用setResult方法汽久,專門用于向上一個活動返回數(shù)據(jù)的。
  3. setResult方法接收兩個參數(shù)踊餐,第一個參數(shù)用于向上一個活動返回處理結(jié)果景醇,一般只使用RESULT_OK或RESULT_CANCELED這兩個值,第二個參數(shù)則把帶有數(shù)據(jù)的intent傳遞回去市袖,然后調(diào)用finish方法銷毀當前活動秀睛。
  4. 由于使用startActivityForResult方法來啟動FirstActivity的甥捺,在FirstActivity被銷毀之后會回調(diào)MainActivity的onActivityResult方法,因此我們需要在MainActivity中重寫這個方法來得到返回的數(shù)據(jù)。
  5. onActivityResult方法帶有三個參數(shù)肃续,第一個參數(shù)requestCode孵奶,就是啟動活動的時候傳入的請求碼伙狐。第二個參數(shù)resultCode氓奈,就是我們在返回數(shù)據(jù)時傳入的處理結(jié)果。第三個參數(shù)data蜓肆,就是攜帶著返回數(shù)據(jù)的Intent颜凯。
  6. 由于一個活動中可能調(diào)用startActivityForResult方法去啟動很多不同的活動,每一個活動返回的數(shù)據(jù)都會回調(diào)到onActivityResult這個方法中仗扬,因此首先要做得就是檢查requestCode的值來判斷數(shù)據(jù)來源症概。確定數(shù)據(jù)是從FirstActivity返回的之后,再通過resultCode的值來判斷處理結(jié)果是否成功早芭。最后從data中取值并打印出來彼城,這樣就完成了向上一個活動返回數(shù)據(jù)的工作。

疑問:
假如FirstActivity中不用按鈕來銷毀活動退个,而是通過點擊Back鍵募壕,那如何處理呢?很簡單:在FirstActivity中重寫onBackPressed方法來解決這個問題语盈。

@Override
public void onBackPressed() {
    Intent intent = new Intent();
    intent.putExtra("data_return","hello");
    setResult(RESULT_OK,intent);
    finish();
}

7. 活動的生命周期

返回棧

Android是用任務(Task)來管理活動的舱馅,一個任務就是一組存放在棧里的活動的集合,這個棧也被稱作返回棧刀荒。

每當我們啟動一個新的活動代嗤,它會在返回棧中入棧,并處于棧頂?shù)奈恢貌琛C慨斘覀儼聪翨ack鍵或調(diào)用finish方法去銷毀一個活動時资溃,處于棧頂?shù)幕顒訒鰲#@時前一個入棧的活動就會重新處于棧頂?shù)奈恢谩?/p>

系統(tǒng)總是會顯示處于棧頂?shù)幕顒咏o用戶烈炭。

活動狀態(tài)

  1. 運行狀態(tài):當一個活動處于棧頂時,這個活動就處于運行狀態(tài)宝恶。
  2. 暫停狀態(tài):當一個活動不處于棧頂符隙,但是依然可見的時候趴捅,這個活動就進入了暫停狀態(tài)。如:對話框后面的活動霹疫。
  3. 停止狀態(tài):當一個活動不處于棧頂拱绑,并且完全不可見的時候,就進入了停止狀態(tài)丽蝎。系統(tǒng)仍然會為這種活動保存相應的狀態(tài)和成員變量猎拨。當其他地方需要內(nèi)存時,活動可能會被系統(tǒng)回收屠阻。
  4. 銷毀狀態(tài):當一個活動從返回棧中移除后就變成了銷毀狀態(tài)红省。
  5. 由于可見的活動被回收,用戶體驗不好国觉,所以系統(tǒng)最不愿意回收運行和暫停狀態(tài)的活動吧恃,當內(nèi)存緊張的時候,會優(yōu)先回收銷毀狀態(tài)和停止狀態(tài)的活動麻诀。

活動的生存期

  • Activity類中定義了7個回調(diào)方法痕寓,覆蓋了活動生命周期的每一個環(huán)節(jié):
  1. onCreate:
    活動第一次被創(chuàng)建的時候調(diào)用,所以在這個活動中完成初始化操作:加載布局蝇闭,綁定事件等呻率。
  2. onStart:
    活動由不可見變?yōu)榭梢姷臅r候調(diào)用。
  3. onResume:
    活動準備好和用戶進行交互的時候調(diào)用呻引。
  4. onPause:
    這個活動在系統(tǒng)準備去啟動或者恢復另一個活動的時候調(diào)用礼仗。通常會在這個方法中將一些消耗CPU的資源釋放掉,以及保存一些關(guān)鍵數(shù)據(jù)苞七,但是這個活動執(zhí)行速度一定要快藐守,不然會影響新的棧頂活動的使用。
  5. onStop:
    這個方法在活動完全不可見的時候調(diào)用蹂风。與onPause方法主要區(qū)別是:如果啟動的新活動是一個對話框式的活動卢厂,那么onPause方法會得到執(zhí)行,而onStop方法并不會惠啄。
    當活動執(zhí)行了onStop方法慎恒,此時另一個優(yōu)先級更高的程序需要內(nèi)存,可能會殺掉進程撵渡,這時再啟動的話融柬,會先執(zhí)行onCreate方法。
  6. onDestory:
    活動被銷毀前調(diào)用趋距。
  7. onRestart:
    活動由停止狀態(tài)變?yōu)檫\行狀態(tài)之前調(diào)用粒氧,即重新啟動時調(diào)用,意思就是當一個活動執(zhí)行了onStop方法节腐,但是并沒有執(zhí)行onDestory方法時外盯,如果被重新啟動摘盆,會執(zhí)行onRestart方法,然后會執(zhí)行onStart方法饱苟,而不會重新執(zhí)行onCreate方法孩擂。
  • 以上活動又分為3種生存期
  1. 完整生存期:活動在onCreate方法和onDestroy方法之間所經(jīng)歷的,就是完整生存期箱熬。
  2. 可見生存期:活動在onStart和onStop方法之間所經(jīng)歷的类垦,就是可見生存期。在這個生存期內(nèi)城须,onStart方法對資源進行加載蚤认,而在onStop方法對資源進行釋放,合理管理對用戶可見的資源酿傍。
  3. 前臺生存期:活動在onResume方法和onPause方法之間就是前臺生存期烙懦。

體驗活動的生命周期

1.創(chuàng)建MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_main);
        Button startNormalActivity = (Button) findViewById(R.id.start_normal_activity);
        Button startDialogActivity = (Button) findViewById(R.id.start_dialog_activity);
        startNormalActivity.setOnClickListener(this);
        startDialogActivity.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.start_normal_activity:
                startActivity(new Intent(this, NormalActivity.class));
                break;
            case R.id.start_dialog_activity:
                startActivity(new Intent(this, DialogActivity.class));
                break;
        }
    }

    @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 onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }

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

2.創(chuàng)建DialogActivity和NormalActivity:

public class DialogActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dialog);
    }
}
public class NormalActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_normal);
    }
}

3.修改配置文件:

<activity android:name=".NormalActivity"></activity>
<activity
    android:name=".DialogActivity"
    android:theme="@style/Theme.AppCompat.Dialog">
</activity>

注意:由于類繼承的是AppCompatActivity,所以主題應該是AppCompat里面的赤炒,否則會報錯氯析。

說明:針對MainActivity

  1. 進入應用程序,MainActivity第一次被創(chuàng)建會依次執(zhí)行onCreate莺褒、onStart掩缓、onResume方法
  2. 啟動NormalActivity,MainActivity會執(zhí)行onPause和onStop方法遵岩,因為NormalActivity把MainActivity完全遮掩住了你辣。
  3. 按下Back返回MainActivity,MainActivity會執(zhí)行onRestart方法尘执,然后執(zhí)行onStart和onResume方法舍哄,因為之前MainActivity已經(jīng)進入了停止狀態(tài),所以onRestart方法誊锭;之所以onCreate方法沒有執(zhí)行表悬,因為MainActvity并沒有重新創(chuàng)建。
  4. 啟動DialogActivity丧靡,MainActivity只會執(zhí)行onPause方法蟆沫,onStop方法并沒有執(zhí)行,因為DialogActivity并沒有完全遮掩住MainActivity温治,MainActivity只是進入了暫停狀態(tài)饭庞,并沒有進入停止狀態(tài)。相應地熬荆,按下Back鍵返回MainActivity也應該只有onResume方法會得到執(zhí)行舟山。
  5. 在MainActivty頁面按下Back鍵推出程序,依次執(zhí)行onPause、onStop捏顺、onDestory方法六孵。

8. 活動被回收了怎么辦

當活動被銷毀以后,可能會銷毀掉活動中原有的數(shù)據(jù)幅骄,比如EditText中輸入的內(nèi)容。為了解決這個問題本今,Android提供了一個onSaveInstanceState回調(diào)方法拆座,這個方法可以保證在活動被回收之前一定會被調(diào)用。

onSaveInstanceState方法會攜帶一個Bundle類型的參數(shù)冠息,Bundle提供了一系列的方法用于保存數(shù)據(jù)挪凑,比如可以使用putString保存字符串,使用putInt方法保存整形數(shù)據(jù)逛艰,以此類推躏碳。每個保存方法需要傳入兩個參數(shù),第一個參數(shù)是鍵散怖,用于后面從Bundle中取值菇绵,第二個參數(shù)是真正要保存的內(nèi)容。

 @Override
    public void onSaveInstanceState(Bundle outState) {
        String tempdata = "something you just typed";
        outState.putString("data_key",tempdata);
        super.onSaveInstanceState(outState);
        Log.e(TAG,"此時被調(diào)用");
    }
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (savedInstanceState!=null){
            String tempdata = savedInstanceState.getString("data_key");
            Toast.makeText(this,"tempdata::"+tempdata,Toast.LENGTH_SHORT).show();
        }
    }

說明:

  1. 利用手機的橫豎屏切換镇眷,可以完美做模擬咬最,先調(diào)用onSaveInstanceState,然后調(diào)用onCreate欠动。
  2. onCreate方法中有一個Bundle類型的參數(shù)永乌。這個參數(shù)在一般情況下都是null,但是如果在活動被系統(tǒng)回收之前有通過onSaveInstanceState方法來保存數(shù)據(jù)的話具伍,這個參數(shù)就會帶有之前所保存的全部數(shù)據(jù)翅雏。

9. 活動的啟動模式和應用場景

啟動模式有4種,分別是standard人芽、singleTop望几、singleTask和singleInstance,可以在配置文件中通過給<activity>標簽指定android:launchMode屬性來選擇啟動模式啼肩。

standard

不管活動是否已經(jīng)在返回棧中存在橄妆,每次啟動都會創(chuàng)建一個新的實例,并且位于棧頂祈坠。

singleTop

在啟動活動時如果發(fā)現(xiàn)返回棧的棧頂已經(jīng)是該活動害碾,則認為可以直接使用它,不會再創(chuàng)建新的活動實例赦拘。

應用場景:下拉欄通知界面點擊進入一個頁面的情景慌随,避免了因為多次啟動導致的需要返回多次的情況。

singleTask

每次啟動該活動時系統(tǒng)首先會在返回棧中檢查是否存在該活動的實例,如果發(fā)現(xiàn)已經(jīng)存在則直接使用該實例,并把在這個活動之上的所有活動統(tǒng)統(tǒng)出棧阁猜,如果沒有發(fā)現(xiàn)就會創(chuàng)建一個新的活動示例丸逸。

應用場景: 例如瀏覽器的主界面。不管從多少個應用啟動瀏覽器剃袍,只會啟動主界面一次黄刚,其余情況都會走onNewIntent,并且會清空主界面上面的其他頁面民效。之前打開過的頁面憔维,打開之前的頁面就ok,不再新建.

singleInstance

啟動一個新的返回棧來管理這個活動畏邢。假設我們的程序中有一個活動是允許其他程序調(diào)用的业扒,如果我們想實現(xiàn)其他程序和我們的程序可以共享這個活動的案例,使用之前的三種模式是做不到的舒萎,因為每個應用程序都有自己的返回棧程储,同一個活動在不同的返回棧中入棧時必然是創(chuàng)建了新的實例。而使用singleInstance模式就可以解決這個問題臂寝,在這個種模式下會有一個單獨的返回棧來管理活動章鲤,不管是哪個應用程序來訪問這個活動,都共用同一個返回棧交煞,也就解決了共享活動實例的問題咏窿。

栗子:FirstActivity跳轉(zhuǎn)到SecondActivity,然后在SecondActivity進入到THirdActivity素征。SecondActivity單獨在一個返回棧集嵌,F(xiàn)irstActivity和THirdActivity在一個返回棧。點擊Back御毅,ThirdActivity直接返回到FirstActivity根欧,再按下Back鍵又會返回到SecondActivity,再按下Back鍵會推出程序端蛆。

原理:FirstA和ThridA存放在同一個返回棧凤粗,當在ThridA的界面按下Back鍵,ThridAcitivy會從返回棧出棧今豆,F(xiàn)irstA成為棧頂活動顯示在界面上嫌拣。在FirstA界面上按下Back鍵,當前的返回棿舳悖空了就顯示了另一個返回棧的棧頂活動异逐,即SecondActivity,按下Back插掂,所有的返回椈艺埃空了腥例,退出程序。

應用場景: 比如通話頁面酝润、鬧鈴提醒頁面.

10. 動態(tài)設置活動的啟動模式

  • FLAG_ACTIVITY_NEW_TASK

舉例說明:經(jīng)過測試燎竖,并沒有開啟一個額外的任務棧,并且會重新創(chuàng)建要销。(如果測試不正確构回,后期會修改)

  • FLAG_ACTIVITY_SINGLE_TOP

舉例說明:棧中有A B C D四個活動,在D中用這個Flag啟動D疏咐,現(xiàn)在棧中有A B C D 四個活動捐凭,D不會重新創(chuàng)建,會回調(diào)onNewIntent方法凳鬓。

  • FLAG_ACTIVITY_CLEAR_TOP

舉例說明:棧中有A B C D 四個活動,在D中用這個Flag啟動B患民,此時棧中只有A B ,B會重新創(chuàng)建缩举。

  • FLAG_ACTIVITY_NO_HISTORY

舉例說明:棧中有A B C D 四個活動,在D中用這個Flag啟動B匹颤,B會重新創(chuàng)建仅孩,此時棧中有A B C D 新B,然后從新B打開C,現(xiàn)在棧中有A B C D C 五個活動印蓖。

  • FLAG_ACTIVITY_BROUGHT_TO-FRONT

舉例說明:我們有A,A打開B,B打開C,C打開D,D然后以這個Flag啟動B, 此時棧的情況就是A,C,D,B辽慕。B不會重新創(chuàng)建,回調(diào)onNewIntent方法赦肃。

  • FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK

舉例說明: 我看郭霖博客溅蛉,這兩個Flag可以讓Activity不會重新創(chuàng)建,但是經(jīng)過我測試他宛,依然會重新創(chuàng)建船侧。(如果測試不正確,后期會修改)

11. 知曉當前是在哪一個活動

創(chuàng)建BaseActivity厅各,讓FirstActivity镜撩、SecondActivity、ThirdActivity繼承BaseAcitify队塘,點擊進入FirstActivity袁梗、SecondActivity、ThirdActivity憔古,Log就會打印出當前活動的名稱遮怜。BaseActivity代碼如下:

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity",getClass().getSimpleName());
    }
}

12.隨時隨地退出程序

  1. 新建ActivityCollector:
public class ActivityCollector {
    public static List<Activity> activities = new ArrayList<>();

    public static void addActivity(Activity activity) {
        activities.add(activity);
    }

    public static void removeActivity(Activity activity) {
        activities.remove(activity);
    }

    public static void finishAll() {
        for (Activity activity : activities) {
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }
}

2.新建BaseActivity:

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity",getClass().getSimpleName());
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }
}

3.新建FirstActivity繼承BaseActivity:

ActivityCollector.finishAll();
android.os.Process.killProcess(android.os.Process.myPid());

說明:

  1. FirstActivity繼承BaseActivity,啟動FirstActivity投放,F(xiàn)irstActivity這個類就會被保存到集合里面奈泪。
  2. 如果FirstActivit被系統(tǒng)內(nèi)存回收銷毀后,集合會把FirstActivit移除。
  3. 想退出程序涝桅,只需清空集合即可拜姿。
  4. 為了保證程序完全退出,殺掉當前進程:killProcess方法用于殺掉一個進程冯遂,它接收一個進程id參數(shù)蕊肥,我們可以通過myPid()方法來獲得當前程序的進程id。

13. 啟動活動的最佳寫法

假設SecondActivity中需要用到兩個非常重要的字符串參數(shù)蛤肌,在啟動MainActivity的時候必須要傳遞過來:

Intent intent = new Intent(this,MainActivity.class);
intent.putExtra("param1","data1");
intent.putExtra("param2","data2");
startActivity(intent);
public static void actionStart(Context context, String data1, String data2) {
        Intent intent = new Intent(context, SecondActivity.class);
        intent.putExtra("param1", data1);
        intent.putExtra("param2", data2);
        context.startActivity(intent);
}
MainActivity.actionStart(this,"data1","data2");
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壁却,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子裸准,更是在濱河造成了極大的恐慌展东,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炒俱,死亡現(xiàn)場離奇詭異盐肃,居然都是意外死亡,警方通過查閱死者的電腦和手機权悟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門砸王,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人峦阁,你說我怎么就攤上這事谦铃。” “怎么了榔昔?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵驹闰,是天一觀的道長。 經(jīng)常有香客問我件豌,道長疮方,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任茧彤,我火速辦了婚禮骡显,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘曾掂。我一直安慰自己惫谤,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布珠洗。 她就那樣靜靜地躺著溜歪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪许蓖。 梳的紋絲不亂的頭發(fā)上蝴猪,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天调衰,我揣著相機與錄音,去河邊找鬼自阱。 笑死嚎莉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的沛豌。 我是一名探鬼主播趋箩,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼加派!你這毒婦竟也來了叫确?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤芍锦,失蹤者是張志新(化名)和其女友劉穎竹勉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娄琉,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡饶米,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了车胡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡照瘾,死狀恐怖匈棘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情析命,我是刑警寧澤主卫,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站鹃愤,受9級特大地震影響簇搅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜软吐,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一瘩将、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凹耙,春花似錦姿现、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至意述,卻和暖如春提佣,著一層夾襖步出監(jiān)牢的瞬間吮蛹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工拌屏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留潮针,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓槐壳,卻偏偏與公主長得像然低,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子务唐,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1.當默認創(chuàng)建一個新項目時雳攘,開發(fā)工具會幫我們創(chuàng)建一個MainActivity.java,以下是用AndroidSt...
    AndrewCheung閱讀 762評論 0 1
  • 1.活動是什么 Activity 活動是最容易吸引用戶的地方枫笛,它是一種可以包含用戶界面的組件吨灭,主要用于和用戶進行交...
    隨心者隨心行閱讀 211評論 0 0
  • 當你決定要學習android的時候,這時候就需要制定一個學習路線刑巧,而我們應該從哪里入手呢喧兄?你可以想象一下,當你打開...
    強大帥閱讀 7,825評論 2 10
  • 因為愛情 不會輕易悲傷 所以一切都是幸福的模樣 因為愛情 簡單的生長 依然隨時可以為你瘋狂 因為愛情 怎么會有滄桑...
    白瑪拉姆閱讀 389評論 0 4
  • 2017-05-09 不必為了取悅別人而妥協(xié)自己啊楚。做自己喜歡做的事吠冤。無須為了別人而將自己置于不開心不舒適的狀...
    弓子閱讀 225評論 0 0