說說 Activity 那些事

hany 7年前發布 | 12K 次閱讀 Activity Android開發 移動開發

Activity就是每一個應用的界面,凡事顯示在app中的界面都是Activity或者由Activity啟動。

基本使用

  • 使用as快捷建立Activity

  • 常規創建
  1. 在app/src/main/AndroidManifest.xml注冊
  2. 編寫java代碼繼承自Activity或者它的子類

自動創建的Activity如下所示:

就是一個activity的標簽

傳遞數據

我們現在創建兩個Activity由MainActivity向SecondActivity傳遞一個字符串“HelloWorld”

  • 在MianActivity中設置帶有數據的intent

  • startActivityForResult啟動activity,第二個參數是請求碼
  • 重寫onActivityResult接受數據

SecondActivity

setResult(666);
        String hello = getIntent().getBundleExtra("hello").getString("nihao");

設置結果碼—>拿到數據

完整代碼

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
//在按鈕中注冊的方法
    public void start(View view) {
        Intent intent = new Intent(MainActivity.this, SecondActivity.class);
        Bundle bundle = new Bundle();
        bundle.putString("nihao", "HelloWorld");
        intent.putExtra("hello", bundle);
        startActivityForResult(intent, 0);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == 666) {
            System.out.println("世界你好");
        }
    }
}



public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        setResult(666);
        String hello = getIntent().getBundleExtra("hello").getString("nihao");

        TextView textView = (TextView) findViewById(R.id.tv);
        textView.setText(hello);
    }

//在按鈕中注冊的方法
    public void finsh(View view) {
        this.finish();
    }
}

生命周期

  1. onCreate方法負責初始化數據、視圖、綁定事件的監聽
  2. onStart和onStop是從是否可見的角度分析
  3. onResume和onPause是從是否在前臺的角度分析
  4. onStart可見不能獲得焦點—>onResume可見能獲得焦點—->onPause可見不能獲得焦點—->onStop不可見不能獲得焦點

Android官方周期

正常的生命周期

onCreate—->onStart——>onResume——>onPause—–>onStop—–onDestory正好6個生命周期

異常生命周期

用戶按主頁鍵

然后再次返回這個activity:

突然來一個電話

生命周期和上面的一樣

當要啟動的另一個Activity主題色是透明的時候那么這時這個Activity不會調用onStop方法

也就是說它還可見,符合邏輯

系統配置改變比如說屏幕旋轉

當前的Activity被銷毀重新創建

在屏幕旋轉的時候會調用onSaveInstanceState和onRestoreInstanceState用來保存和恢復組件的狀態(注意as默認創建的Activity繼承自AppCompatActivity,這里的兩個方法要使用使用AppCompatActivity中的)

當狀態改變調用onSaveInstanceState保存狀態然后調用onRestoreInstanceState恢復狀態:

旋轉屏幕時狀態分析

當屏幕發生旋轉后數據會保存到savedInstanceState和onCreate方法中的savedInstanceState

protected void onRestoreInstanceState(Bundle savedInstanceState)

橙色線表示屏幕旋轉

那么會保存view的哪些信息呢?這要看對應的view的onSaveInstanceState方法,比如EditText的正在編輯的信息就會丟失。

那么怎么屏蔽屏幕旋轉的信息呢???

—————–看法寶——————-

只要在activity注冊的時候加入configChanges標簽就可以,注意假如是屏蔽旋轉的話應該是orientation|screenSize兩個屬性

從此媽媽再也不用擔心我的學習了,哈哈哈!!!!

####鎖屏和屏幕解鎖

只是調用了onPause和onStop沒有銷毀Activity

###可見性

activity的完整生存期會在 onCreate() 調用和 onDestroy() 調用之間發生。

activity的可見生存期會在 onStart() 調用和 onStop() 調用之間發生。系統會在activity的整個生存期內多次調用 onStart() 和onStop(), 因為activity可能會在顯示和隱藏之間不斷地來回切換。

activity的前后臺切換會在 onResume() 調用和 onPause() 之間發生。 因為這個狀態可能會經常發生轉換,為了避免切換遲緩引起的用戶等待,這兩個方法中的代碼應該相當地輕量化。

activity回收和保存信息

onSaveInstanceState方法

在activity 可能被回收之前 調用,用來保存自己的狀態和信息,以便回收后重建時恢復數據(在onCreate()或onRestoreInstanceState()中恢復)。旋轉屏幕重建activity會調用該方法,但其他情況在onRause()和onStop()狀態的activity不一定會調用 ,下面是該方法的文檔說明。

系統靈活的來決定調不調用該方法, 但是如果要調用就一定發生在onStop方法之前,但并不保證發生在onPause的前面還是后面。

onRestoreInstanceState方法

這個方法在onStart 和 onPostCreate之間調用,在onCreate中也可以狀態恢復,但有時候需要所有布局初始化完成后再恢復狀態。

啟動模式

就是啟動Activity的方式:

只要在Activity中指定launchMode屬性就可以完成啟動模式的改變。

在上面的案例中我們從MainActivity到SecondActivity有木有發現不按下結束鍵只是返回也能返回到MainActivity,我擦MainActivty那家伙還活著呢??讓我們探究下正常的啟動模式

正常的啟動模式

就是先啟動的Activity先入棧,出棧是最后出棧,所以當SecondActivity死后,可以看見MianActivity,在MainActivity中添加一個不斷重新啟動自己的button

然后進入Terminal:adb shell 然后dumpsys activity

查看當前運行的activity:

每一個都在棧中。

新建一個Activity2項目在其中只是設置一個按鈕,啟動Activity項目中的MianActivity:

發現Activity中的Mian在項目2的棧內,于是有一個結論:

正常模式啟動的Activity,誰啟動它,它就在那一個棧

跨應用啟動Activity代碼

Intent intent = new Intent();     intent.setClassName("win.haotinayi.activity","win.haotinayi.activity.MainActivity");

就是設置包名,在設置Activity的全名

SingleTop

就是當要啟動的Activity恰好在棧頂的時候,那么就不再重復創建:

無論怎么啟動都只有一個實例。

SingleTask

棧內單例模式,分為三種情況:

  1. 當有Activity需要的棧時,并且是棧頂,啥也不說了,直接復用
  2. 當有Activity需要的棧時,并且不是棧頂,那么在它上面的全部干掉,自己當大哥
  3. 當沒有Activity需要的棧時,創建棧

把MianActivity設置成SingleTask模式,首先打開Activity項目,讓兩個Activity同時存在:

并且MianActivity不是棧頂,然后在通過Activity2打開MainActivity:

SecondActivity被干掉了,大哥是MianActivity,那么什么是Activity的需要棧呢? 默認是包名

使用屬性taskAffinity可以改掉,現在來一個惡作劇:

這時再次啟動項目發現,項目的棧改變了:

SingleInstance

Activity只能單獨存在一個棧中,換句話說就是整個手機就你一個實例

使用Intent來標示啟動模式

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);

####標志的分類

  • FLAG_ACTIVITY_NEW_TASK

與”singleTask”模式相同,在新的 task 中啟動 activity。如果要啟動的 activity 已經運行于某 task 中,則那個 task 將調入前臺。

  • FLAG_ACTIVITY_SINGLE_TOP

與 “singleTop”模式相同,如果要啟動的 activity位于back stack 頂,系統不會重新創建目標Activity實例,而是直接復用Task棧頂的Activity。

  • FLAG_ACTIVITY_CLEAR_TOP

此種模式在launchMode中沒有對應的屬性值。如果要啟動的 activity 已經在當前 task 中運行,則不再啟動一個新的實例,且所有在其上面的 activity 將被銷毀。

Activity優先級

從高到低排序:

  1. 顯示且能獲得焦點(前臺)的Activity
  2. 顯示不能獲得焦點(非前臺),一個打開Dialog的Activity
  3. 不可見,已經處于暫停或者直接onStop后的Activity

當內存不足的時候低優先級的Activity就會被殺掉,如果一個組件沒有放在四大組件中,那么很快被殺死,所以后臺任務最好放到一個四大組件中,防止被干掉。

注意

Activity的全屏

// 去除標題欄
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

requestWindowFeature要在setContentView調用之前否則會崩潰

Activity的公開性

一般設置Activity為非公開的

<activity  
...... 
android:exported="false" />

注意:非公開的Activity不能設置intent-filter,以免被其他activity喚醒(如果擁有相同的intent-filter)。

 

來自:http://haotianyi.win/2017/03/01/01-說說Activity那些事/

 

 本文由用戶 hany 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!