麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

安卓開發筆記——深入Activity

2019-11-15 01:18:21
字體:
來源:轉載
供稿:網友
安卓開發筆記——深入Activity

  在上一篇文章《安卓開發筆記——重識Activity》中,我們了解了Activity生命周期的執行順序和一些基本的數據保存操作,但如果只知道這些是對于我們的開發需求來說是遠遠不夠的,今天我們繼續探索Activity,來了解下關于Activity任務棧和Activity四種啟動模式的區別。

  為什么需要了解關于Activity的任務棧,其實最直接的體現就是提高用戶交互友好性。

  舉個例子,當我們去瀏覽一個新聞客戶端的時候,我們進入了新聞詳情頁,在這個頁面有相隔兩條的新聞標題,當我們去點擊這個標題的時候進入了新的新聞詳情頁時,如果我們不加以控制會導致什么現象?它會創建出n個新聞詳細頁的Activity實例,導致用戶在退出的時候需要推出多個新聞詳情activity,這點在用戶體驗上是非常不好的,當然對于我們自身的程序也是非常不好的,不斷的去創建新的Activity必定會消耗一定的內存,久而久之,應用程序會越來越卡甚至崩潰。在我之前寫過的博文《安卓開發筆記——打造屬于自己的博客園APP(四)》中也應用到了這一知識點。

  

在講Activity任務棧前,我們應該先知道什么是棧?

  簡單點來理解,可以把棧比作一個開封的箱子,我們可以往里面塞東西,這里假設塞的東西的底面積和箱子的底面積是相同的,那么這些東西就具備有從下往上一定的順序,當我們想要取出箱子里面的東西時,我們沒有辦法一下子拿到箱子最底層的東西,我們只能拿到最上面一層的東西,從上往下。

  來看下這張圖,這里的箱子就是棧,箱子口可以看作是棧的入口與出口,東西代表數據。棧的特點:具有一定的次序,后進先出(越先放入的東西,越晚出來)。

1、Activity任務棧  

 好了,在了解了什么是棧之后,我們可以開始進入今天的主題了,在Android的官方文檔描述中我們可以知道,任務棧也是棧,具有棧的一切特點。

  Activity任務棧,顧名思義是存放Activity任務的棧,這里的任務棧為上圖箱子,Activity為上圖的東西。

  當我們每打開一個Activity的時候它會就往Activity任務棧中壓入一個Activity,當我們每銷毀一個Activity的時候它會從Activity任務棧中彈出一個Activity,由于安卓系統自身的設計,我們只能在手機屏幕上獲取當前一個Activity的焦點即棧頂元素(最上面的Activity),其余的Activity會暫居后臺等待系統調用。

1.1、關于任務棧的概念:

任務棧是用來提升體驗而設計的:
(1) 程序打開時就創建了一個任務棧, 用于存儲當前程序的activity,當前程序(包括被當前程序所調用的)所有的activity屬于一個任務棧。
(2) 一個任務棧包含了一個activity的集合, 可以有序的選擇哪一個activity和用戶進行交互,只有在任務棧棧頂的activity才可以跟用戶進行交互。
(3) 任務棧可以移動到后臺,并且保留了每一個activity的狀態. 并且有序的給用戶列出它們的任務, 而且還不丟失它們狀態信息。
(4) 退出應用程序時,當把所有的任務棧中所有的activity清除出棧時,任務棧會被銷毀,程序退出。

1.2、關于任務棧的缺點:

(1) 每開啟一次頁面都會在任務棧中添加一個Activity,而只有任務棧中的Activity全部清除出棧時,任務棧被銷毀,程序才會退出,這樣就造成了用戶體驗差,需要點擊多次返回才可以把程序退出了。
(2) 每開啟一次頁面都會在任務棧中添加一個Activity還會造成數據冗余重復數據太多,會導致內存溢出的問題(OOM)。

2、Activity的4種啟動方式

  為了解決任務棧產生的問題,Android為Activity設計了啟動模式,那么下面的內容將介紹Android中Activity的啟動模式,這也是最重要的內容之一。

  啟動模式(launchMode)在多個Activity跳轉的過程中扮演著重要的角色,它可以解決是否生成新的Activity實例,是否重用已經存在的Activity實例,是否和其他實例共用一個任務棧。任務棧是一個具有棧結構的對象,一個任務棧可以管理多個Activity,每啟動一個應用,也就創建一個與之對應的任務棧。

  Activity一共有以下四種launchMode模式:1、standard 2、singTop 3、singTask 4、singleInstance,我們可以在AndroidManifest.xml配置<activity>的android:launchMode屬性為以上四種之一即可。
2.1、實踐是檢驗真理的唯一標準
 下面寫個實例,有2個Activity,每個Activity都有一個跳轉按鈕,第一個Activity點擊按鈕跳轉第二個Activity,第二個Activity點擊按鈕跳轉自身。
 1 package com.lcw.rabbit.activitydemo; 2  3 import android.app.Activity; 4 import android.content.Intent; 5 import android.os.Bundle; 6 import android.util.Log; 7 import android.view.View; 8 import android.widget.Button; 9 10 public class MainActivity extends Activity {11 12     PRivate static final String TAG = "Rabbit";13 14     private Button mbButton;15 16     @Override17     protected void onCreate(Bundle savedInstanceState) {18         super.onCreate(savedInstanceState);19         setContentView(R.layout.activity_main);20 21         Log.i(TAG,"第一個Activity,加入任務棧:"+getTaskId());22 23         //點擊按鈕跳轉第二個Activity24         mbButton = (Button) findViewById(R.id.bt_button);25         mbButton.setOnClickListener(new View.OnClickListener() {26             @Override27             public void onClick(View v) {28                 startActivity(new Intent(MainActivity.this, SecondActivity.class));29             }30         });31 32 33     }34 35     @Override36     protected void onDestroy() {37         super.onDestroy();38         Log.i(TAG, "第一個Activity,退出任務棧:" + getTaskId());39     }40 }
MainActivity.java
 1     package com.lcw.rabbit.activitydemo; 2  3     import android.app.Activity; 4     import android.content.Intent; 5     import android.os.Bundle; 6     import android.util.Log; 7     import android.view.View; 8     import android.widget.Button; 9 10     public class SecondActivity extends Activity {11 12         private static final String TAG = "Rabbit";13         private Button mbButton1;14         private Button mbButton2;15 16         @Override17         protected void onCreate(Bundle savedInstanceState) {18             super.onCreate(savedInstanceState);19             setContentView(R.layout.activity_second);20             Log.i(TAG, "第二個Activity,加入任務棧:" + getTaskId());21             //點擊按鈕跳轉第二個Activity22             mbButton1 = (Button) findViewById(R.id.bt_button1);23             mbButton1.setOnClickListener(new View.OnClickListener() {24                 @Override25                 public void onClick(View v) {26                     startActivity(new Intent(SecondActivity.this, MainActivity.class));27                 }28             });29             mbButton2 = (Button) findViewById(R.id.bt_button2);30             mbButton2.setOnClickListener(new View.OnClickListener() {31                 @Override32                 public void onClick(View v) {33                     startActivity(new Intent(SecondActivity.this, SecondActivity.class));34                 }35             });36         }37 38         @Override39         protected void onDestroy() {40             super.onDestroy();41             Log.i(TAG, "第二個Activity,退出任務棧:" + getTaskId());42         }43     }
SecondActivity.java

  

實驗一:啟動模式standard  

  系統默認的Activity啟動模式是standard,我們這里為了檢驗再設置一下:

 1         <activity 2             android:name=".MainActivity" 3             android:launchMode="standard"> 4             <intent-filter> 5                 <action android:name="android.intent.action.MAIN" /> 6                 <category android:name="android.intent.category.LAUNCHER" /> 7             </intent-filter> 8         </activity> 9         <activity10             android:name=".SecondActivity"11             android:launchMode="standard"></activity>

  現在我們進入第一個Activity的時候,點擊按鈕啟動第二個Activity,看下當前任務棧:

  當我們點擊第二個Activity的按鈕,讓它跳轉自身,看下當前任務棧:

  當我們按下Back鍵,跳轉第一個Activity,銷毀第二個Activity時,看下當前任務棧:

  可以發現,這個任務棧和我們剛上圖描述的箱子(Activity任務棧)是一致的,從上往下放東西(Activity),越晚放進去的東西(Activity)在越上面,而后面的t1072則代表當前任務棧的編號ID,ID相同代表它們屬于同一個任務棧。

  我們從日志文件中也可以看得很清楚:

實驗一結論:

  在Activity啟動模式為standard(默認)的情況下,不管之前有沒有Activity實例,每一次啟動Activity都會創建一個新的Activity實例,并置于Activity任務棧棧頂。

實驗二:啟動模式singleTop

 1        <activity 2             android:name=".MainActivity" 3             android:launchMode="standard"> 4             <intent-filter> 5                 <action android:name="android.intent.action.MAIN" /> 6                 <category android:name="android.intent.category.LAUNCHER" /> 7             </intent-filter> 8         </activity> 9         <activity10             android:name=".SecondActivity"11             android:launchMode="singleTop"></activity>

  現在我們進入第一個Activity點擊按鈕跳轉第二個Activity,然后再點擊按鈕跳轉自身,看下當前任務棧:

  系統日志文件:

  然后我們再點擊按鈕啟動第一個Activity,然后點擊按鈕啟動第二個Activity,看下當前任務棧:

  系統日志:

實驗二結論:

  在Activity啟動模式為singleTop(棧頂任務唯一)的情況下,如果當前Activity處于棧頂,那么它就不會再去實例化一個新的Activity,當Activity不處于棧頂的時候,會重新實例化一個新的Activity并置于棧頂,此時的任務棧編號為1080。

實驗三:啟動模式singleTask

 1         <activity 2             android:name=".MainActivity" 3             android:launchMode="standard"> 4             <intent-filter> 5                 <action android:name="android.intent.action.MAIN" /> 6                 <category android:name="android.intent.category.LAUNCHER" /> 7             </intent-filter> 8         </activity> 9         <activity10             android:name=".SecondActivity"11             android:launchMode="singleTask"></activity>

  當我們進入第一個Activity點擊進入第二個,再啟動自身,看下當前任務棧:

  系統日志:

  現在我們點擊啟動第一個Activity,再點擊啟動第二個Activity,看下當前任務棧:

  系統日志:

實驗三結論:

  在Activity啟動模式為singleTask(唯一實例)的情況下,當啟動Activity的時候,如果當前Activity不存在則實例化一個新的Activity,如果當前Activity在任務棧中已經存在,則會復用這個Activity實例,但這邊我們從日志打印可以看出在啟動第二個Activity的時候,第一個Activity推出了任務棧,也就意味著當啟動模式為singTask的時候,啟動已經存在在Activity任務棧中但不在棧頂的Activity時,該Activity會把壓在它前面的所有Activity彈出任務棧,此時任務棧編號為1081,屬于同一個任務棧。

實驗四:啟動模式singleInstance

 1         <activity 2             android:name=".MainActivity" 3             android:launchMode="standard"> 4             <intent-filter> 5                 <action android:name="android.intent.action.MAIN" /> 6                 <category android:name="android.intent.category.LAUNCHER" /> 7             </intent-filter> 8         </activity> 9         <activity10             android:name=".SecondActivity"11             android:launchMode="singleInstance"></activity>

  現在我們進入第一個Activity點擊按鈕跳轉第二個Activity,再讓其跳轉自身,看下當前任務棧:

  系統日志:

  現在點擊按鈕啟動第一個Activity,再點擊按鈕啟動第二個Activity,看下當前任務棧:

  系統任務:

  點擊Back鍵,直到程序完全退出,看下系統日志:

實驗四結論:

  在Activity啟動模式為singleInstance的情況下,首先我們可以發現的是啟動模式為singleInstance的Activity處于不同的任務棧(Task編號不同),并保證不再有其他的Activity實例進入,它還是和singleTask一樣保持唯一實例,然后它的退出順序是不再是根據調用順序,而是在不同的任務棧中,從上往下退出。

在共用一個Activity實例時,期間發生了什么?

  在上訴模式中,當我們的Activity涉及到同一實例的時候,期間Activity做了哪些事情?在Android官方文檔中我們可以知道期間雖然沒有新實例化一個Activity,但是調用了onNewIntent方法。

  現在我們在第二個Activity里添加一個onNewIntent方法:

1         @Override2         protected void onNewIntent(Intent intent) {3             super.onNewIntent(intent);4             Log.i(TAG, "第二個Activity,執行onNewIntent");5         }

1、在standard(默認)啟動模式下,我們來回的去跳轉Activity,看下日志打印,發現是不會調用onNewIntent方法的,因為它不是一個實例。

2、在singleTop模式下,我們從第一個Activity跳轉到第二個Activity,再從第二個Activity跳轉自身,再跳轉第一個Activity,看下日志打印,我們可以發現,當第二個Activity置于棧頂的時候,由于重用了實例,所以調用了onNewIntent方法。

3、當singleTask和singleInstance模式下也是一樣的,因為重用了實例,所以會調用onNewIntent方法,且onNewIntent方法是在前一個Activity的onStop方法后(當前ActivityonReStart方法前)立即調用的。

好了,今天先寫到這里,有什么建議或疑問,可以在文章評論給我留言。

作者:李晨瑋出處:http://www.companysz.com/lichenwei/本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,日后必有一番作為!旁邊有“推薦”二字,你就順手把它點了吧,相得準,我分文不收;相不準,你也好回來找我!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 一区二区三区在线观看国产 | 国产免费看| 污视频在线免费 | 最新中文字幕在线视频 | 91成人一区二区三区 | 欧美成人se01短视频在线看 | 日本成人一区二区 | 国产一级在线观看视频 | 欧美一级黄色免费 | 国产精品白嫩白嫩大学美女 | 27xxoo无遮挡动态视频 | 欧美成人三级视频 | 特逼视频 | 成人免费电影在线观看 | 91九色视频在线观看 | 爽爽淫人网 | 毛片视频观看 | 免费国产一区 | 国产精品视频一区二区三区四区国 | 污片视频网站 | 国产亚洲精品久久久久久久久 | 李宗瑞国产福利视频一区 | 校花被肉干高h潮不断 | 国产99久久久久 | 久久69精品久久久久久国产越南 | 国产一国产一级毛片视频在线 | 亚洲综合视频网站 | 激情大乳女做爰办公室韩国 | 亚洲欧美一区二区三区在线观看 | 国产乱一区二区三区视频 | 国产中出视频 | 国产精品美女久久久久久不卡 | 狼伊千合综网中文 | av老司机久久 | 国产一精品一av一免费爽爽 | cosplay裸体福利写真 | 福利在线国产 | 天天夜夜操操 | 91中文在线观看 | 97精品视频在线观看 | 国产精品久久久久久久久久久久久久久 |