Android——Activity

描述:

1、表示用戶交互的一個界面(活動),每一個activity對應一個界面。
2、是所有View的容器。
3、有個ActivityManager的管理服務類,用于維護與管理Activity的啟動與銷毀。Activity啟動時,會把Activity的引用放入任務棧中。
4、一個應用程序可以被別的應用程序的activity開啟此時,是將此應用程序的引用加入到了開啟的那個activity的任務棧中了。

創建Activity

1、定義類繼承自Activity類;
2、在清單文件中Application節點中聲明<activity>節點;

啟動Activity

顯示啟動:

啟動當前應用內的Activity,這樣的啟動方式比較快速。

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

隱示啟動

一般用于調用其他應用的Activity,創建Intent后指定動作和數據以及類型。
1、啟動系統自帶應用

//  ex:撥打電話(Android6.0注意申請權限)
Intent intent = new Intent();     
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel://123456"));          
startActivity(intent);

//ex:打開網頁
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);

2、啟動第三方應用

//1、啟動主Acitvity
//Intent intent = new Intent(Intent.ACTION_MAIN);
//intent.addCategory(Intent.CATEGORY_LAUNCHER);

//有 <intent-filter>標簽的Activity默認  android:exported="true"
Intent intent = new Intent();
//參數是包名,類全限定名,注意直接用類名不行
ComponentName cn = new ComponentName("com.example.liucun.myapplication",
"com.example.liucun.myapplication.MainActivity");
intent.setComponent(cn);
startActivity(intent);

//2、啟動非主Activity
//必須要在manifest里面設置exported屬性為true,表示此activity對外公開,才能直接跳轉。 
Intent intent = new Intent();
intent.setClassName("com.example.liucun.myapplication",
    "com.example.liucun.myapplication.test.SecondActivity");
startActivity(intent);

Activity生命周期

1、Acitivity三種狀態
a、運行:activity在最前端運行;
b、暫停:activity可見,但前端還有其他activity,注意:在當前Activitiiy彈出的對話框是Activity的一部分,彈出時,不會執行onPause方法;
c、停止:activity不可見,完全被覆蓋;

2、生命周期相關的方法(都是系統自動調用,都以 on 開頭):
a. onCreate: 創建時調用,或者程序在暫停、停止狀態下被殺死之后重新打開時也會調用;
b. onStart: onCreate之后或者從停止狀態恢復時調用;(界面可見)
c. onResume: onStart之后或者從暫停狀態恢復時調用,從停止狀態恢復時由于調用onStart,也會調用onResume(界面獲得焦點);
d. onPause: 進入暫停、停止狀態,或者銷毀時會調用(界面失去焦點);
e. onStop: 進入停止狀態,或者銷毀時會調用;(界面不可見)
f. onDestroy: 銷毀時調用;
g. onRestart: 從停止狀態恢復時調用;

圖片.png

橫豎屏切換與信息的保存和恢復

1、切換橫豎屏時,會自動查找layout-port 、layout-land中的布局文件。
2、默認情況下,切換時,將執行摧毀onPause onStop onDestroy,再重置加載新的布局onCreate onStart onResume。
3、切換時如果要保存數據, 可以重寫: onSaveInstanceState();
恢復數據時, 重寫: onRestoreInstanceState()。
4、固定橫屏或豎屏:android:screenOrientation="landscape"
橫豎屏切換, 不摧毀界面(程序繼續執行) android:configChanges="orientation|keyboardHidden|screenSize"
5、保存信息狀態的相關方法:
a. onSaveInstanceState:
在Activity被動的摧毀或停止的時候調用(如橫豎屏切換,來電),用于保存運行數據,可以將數據存在在Bundle中;
b. onRestoreInstanceState:
該方法在Activity被重新繪制的時候調用,例如改變屏幕方向,onSavedInstanceState可為onSaveInstanceState保存的數據

    private String temp;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        // 從savedInstanceState中恢復數據, 如果沒有數據需要恢復savedInstanceState為null  
        if (savedInstanceState != null) {  
            temp = savedInstanceState.getString("temp");  
            System.out.println("onCreate: temp = " + temp);  
        }  
    }  
        
    // 將數據保存到outState對象中, 該對象會在重建activity時傳遞給onCreate方法  
    @Override  
    protected void onSaveInstanceState(Bundle outState) {  
        super.onSaveInstanceState(outState);  
        outState.putString("temp", temp);  
    }  

Activity四種啟動模式

任務棧的概念

一個手機里面有多少個任務棧:
一般情況下,有多少個應用正在運行,就對應開啟多少個任務棧;
一般情況下,每開啟一個應用程序就會創建一個與之對應的任務棧;
二般情況下,如launchMode為 singleInstance,就創建自己單獨的任務棧;

任務棧的作用

1、它是存放Activity的引用的,Activity不同的啟動模式,對應不同的任務棧的存放;
2、可通過getTaskId()來獲取任務棧的ID,如果前面的任務棧已經清空,新開的任務棧ID+1,是自動增長的;

啟動模式

在AndroidManifest.xml中的<activity>標簽中可以配置android:launchMode屬性,用來控制Actvity的啟動模式;在Android系統中我們創建的Acitivity是以棧的形式呈現的:
1、standard:默認的,每次調用startActivity()啟動時都會創建一個新的Activity放在棧頂;
2、singleTop:啟動Activity時,指定Activity不在任務棧棧頂就創建,如在棧頂,則不會創建,會調用onNewInstance(),復用已經存在的實例
3、singleTask:在任務棧里面只允許一個實例,如果啟動的Activity不存在就創建,如果存在直接跳轉到指定的Activity所在位置,如:棧內有ABCD,D想創建A, 即A上的BCD相應的Activity將移除;
4、singleInstance:(單例)開啟一個新的任務棧來存放這個Activity的實例,在整個手機操作系統里面只有一個該任務棧的實例存在,此模式開啟的Activity是運行在自己單獨的任務棧中的;

啟動模式的使用場景

1、singleTop
a:消息推送,通知欄彈出Notification,點擊Notification跳轉到指定Activity,但是如果我現在頁面就停留在那個指定的Activity,會再次打開我當前的Activity,這樣返回的時候回退的頁面和當前頁面一樣,感官上就會很奇怪。
b:登錄的時候,登錄成功跳轉到主頁,按下兩次登錄按鈕,生成了兩個主頁。一些有啟動延遲的頁面(往往是動畫,網絡造成)也會有這樣的情況。

2、singleTask
a:應用的MainActivity可以使用singleTask模式,保證只有一個主頁實例的存在。并且也可以配合整個APP的退出,即在任何頁面結束當前應用可以跳轉到singleTask模式的MainActivity,然后再finish() MainActivity。

3、singleInstance
a:Launcher,即桌面
b:呼叫來電界面

應用程序、進程、任務棧的區別

1、應用程序
四大組件的集合在清單文件中都放在application節點下,對于終端用戶而言,會將其理解為activity。
2、進程
操作系統分配的獨立的內存空間,一般情況下,一個應用程序會對應一個進程,特殊情況下,會有多個進程,一個應用程序會對應一個或多個進程。
3、任務棧:
task stack(back stack)后退棧,記錄用戶的操作步驟,維護用戶的操作體驗,專門針對于activity而言的,只用于activity;一般使用standard,其他情況用別的。

Activity內存管理

Android系統在運行多個進程時,如果系統資源不足,會強制結束一些進程,優先選擇哪個進程來結束是有優先級的。
會按照以下順序殺死:
1、空: 進程中沒有任何組件;
2、后臺:進程中只有停止狀態的Activity;
3、服務:進程中有正在運行的服務;
4、可見:進程中有一個暫停狀態的Activity;
5、前臺:進程中正在運行一個Activity;
一個任務棧所有Activity在退出的時候進程不會銷毀, 會保留一個空進程方便以后啟動. 但在內存不足時進程會被銷毀;
Activity中不要在Activity做耗時的操作, 因為Activity切換到后臺之后(Activity停止了), 內存不足時, 也容易被銷毀;

空進程:任務棧清空,意味著程序退出了,但進程留著,這個就是空進程,容易被系統回收;

Activity內存泄漏

非靜態內部類和匿名內部類持有Activity的引用

在Java中,內部類的定義與使用一般為成員內部類與匿名內部類,他們的對象都會隱式持有外部類對象的引用,影響外部類對象的回收。

GC只會回收沒有被引用或者根集不可到達的對象,內部類在生命周期內始終持有外部類的對象的引用,造成外部類的對象始終不滿足GC的回收條件,反映在內存上就是內存泄露。如:Activity的內存泄露。
ex:

public class SampleActivity extends Activity {
  private final Handler mLeakyHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      // ...
    }
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 十分鐘后發送一條消息
    mLeakyHandler.postDelayed(new Runnable() {
      @Override
      public void run() { /* ... */ }
    }, 1000 * 60 * 10);

    // Go back to the previous Activity.
    finish();
  }
}

當我們執行了Activity的finish方法,被延遲的消息會在被處理之前存在于主線程消息隊列中10分鐘,而這個消息中又包含了Handler的引用,而Handler是一個匿名內部類的實例,其持有外面的SampleActivity的引用,所以這導致了SampleActivity無法回收,進行導致SampleActivity持有的很多資源都無法回收,這就是我們常說的內存泄露。

注意上面的new Runnable這里也是匿名內部類實現的,同樣也會持有SampleActivity的引用,也會阻止SampleActivity被回收。

解決方案:

1、將內部類定義為static;
2、使用弱引用修飾外部類Activity。

public class SampleActivity extends Activity {

  private static class MyHandler extends Handler {
    private final WeakReference<sampleactivity> mActivity;

    public MyHandler(SampleActivity activity) {
      mActivity = new WeakReference<sampleactivity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
      SampleActivity activity = mActivity.get();
      if (activity != null) {
        // ...
      }
    }
  }

  private final MyHandler mHandler = new MyHandler(this);

  private static final Runnable sRunnable = new Runnable() {
      @Override
      public void run() { /* ... */ }
  };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mHandler.postDelayed(sRunnable, 1000 * 60 * 10);

    finish();
  }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,725評論 25 708
  • Activity https://developer.android.com/guide/components/a...
    XLsn0w閱讀 715評論 0 4
  • 這個標題被不同的方式表達過,最近的應該是韓寒在《后會無期》里說的"聽過很多道理,依然過不好這一生"。 劉未鵬在《...
    周偉誠閱讀 158評論 0 0
  • 我火紅的身軀為你綻放 一起在地獄的彼岸歌唱 然而 不知什么時候 你已悄然退場 只剩我 和這一身的傷
    苦命的苦瓜閱讀 278評論 0 0
  • 拍花,閑情逸致,調整自我?態。佛曰:一花一世界,一葉一菩提。這就是一種境界,有人理解有人也不理解。 拍花,也是練就...
    咖啡莫回味閱讀 382評論 2 0