編輯:關於Android編程
今天花了整個下午+晚上的的時間學習了Activity的啟動模式,本來以為這個知識點很簡單,但是在學習的過程中發現,Activity的啟動模式並沒有自己想象的那麼簡單,下面我們一起來看看這Activity的四種啟動模式吧,如有疑問歡迎留言,如有謬誤歡迎大家批評指正,謝謝
Activity的啟動模式共有四種
1.standard
2.singleTop
3.singleTask
4.singleInstance
如圖所示:LaunchMode在多個Activity跳轉的過程中扮演著重要的角色,它可以決定是否生成新的Activity實例,是否重用已存在的Activity實例,是否和其他Activity實例公用一個task裡。這裡簡單介紹一下task的概念,task是一個具有棧結構的對象,一個task可以管理多個Activity,啟動一個應用,也就創建一個與之對應的task。
下面我們就依次來說說這幾種啟動模式
1.standard
standard模式是Activity默認的啟動模式,當我們在沒有配置activity的launchMode時它就會按照standard方式去啟動,
下面通過一個實例來解釋下這種啟動模式
FirstActivity代碼如下:
package com.example.activitylauchmodepractice; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class FirstActivity extends Activity { private Button btn_jumpToSecondActivity; private TextView tv_showViewClass; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first); tv_showViewClass=(TextView) findViewById(R.id.tv_showViewClass); tv_showViewClass.setText(FirstActivity.this.toString()); btn_jumpToSecondActivity=(Button) findViewById(R.id.btn_jumpToSecondActivity); btn_jumpToSecondActivity.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(FirstActivity.this,FirstActivity.class); startActivity(intent); } }); } }啟動後的界面
此時它所對應的任務棧如下
在此基礎上我們點擊按鈕再次啟動Activity此時的界面如下
此時的任務棧變化過程如下
我們再次點擊按鈕跳轉到FirstActivity界面如下
此時的任務棧的變化過程如下
好了到這我們就可以分析一下了,在上述過程中我們點擊了三次按鈕它實例化了三個FirstActivity
這就是standard模式的特點:不管任務棧中有沒有實例存在它都會實例化一個Activity
當我們點擊返回按鈕時它會依次把最上面的Activity出棧,上面的過程中一共實例化了三個Activity因此我們需要點擊三次返回按鈕應用才能退出。
2.singleTop
還用上面那個例子,此時我們給FirstActivity的屬性指定為:android:launchMode=singleTop
啟動後的界面
此時的任務棧如下
我們接著點擊按鈕發現無論點擊幾次界面都沒變說明它只實例化一次,此時的任務站始終是一個Activity此時點擊一次返回鍵便可退出應用。
這是只有一個Activity的情況,下面我們說說多個Activity的情況
再來一個SecondActivity代碼如下:
package com.example.activitylauchmodepractice; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class SecondActivity extends Activity { private Button btn_jumpToFirstActivity_; private TextView tv_showViewClass; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); tv_showViewClass=(TextView) findViewById(R.id.tv_showViewClass); tv_showViewClass.setText(SecondActivity.this.toString()); btn_jumpToFirstActivity_=(Button) findViewById(R.id.btn_jumpToFirstActivity); btn_jumpToFirstActivity_.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(SecondActivity.this, FirstActivity.class); startActivity(intent); } }); } }把FirstActivity的代碼稍作修改
btn_jumpToSecondActivity.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(FirstActivity.this,SecondActivity.class); startActivity(intent); } });在上面的Activity中FirstActivity的啟動模式是singleTop,SecondActivity的啟動模式是默認的standard,做好准備之後我們來做操作
啟動後的界面如下:
此時的任務棧如下
在此基礎上我們點擊一次按鈕界面如下
此時的任務棧的變化如下
在SecondActivity中再次點擊按鈕的界面如下
此時的任務棧的變化如下
從上面的過程中我們看到再次從SecondActivity跳轉到FirstActivity時兩次的FirstActivity的序列號不同說明又重新生成了一個FirstActivity
singleTop模式的特點:當從SecondActivity跳轉到FirstActivity時,系統發現存在有FirstActivity實例,但不是位於棧頂,於是重新生成一個實例。這就是singleTop啟動模式的特點,即如果發現有對應的Activity實例正位於棧頂,則重復利用,不再生成新的實例,如果棧頂沒有對應的Activity則實例化一個。
該模式和standard模式基本一致,但有一點不同,當將要被啟動的Activity已經位於Task棧頂時,系統不會重新創建目標Activity的實例,而是直接復用Task棧頂的Activity
3.singleTask(內單例模式)
我們還是建立在上面的基礎上,把FirstActivity的啟動模式改為android:launchMode=singleTask
啟動後我們點擊三次跳轉按鈕界面如下圖所示
在上面的過程中,FirstActivity的序列號是不變的,SecondActivity的序列號是改變的,說明從SecondActivity跳轉到FirstActivity時,沒有生成新的實例,但是從FirstActivity跳轉到SecondActivity時生成了新的實例。
在此過程中任務棧的變化過程如下
在上面的跳轉過程中當從SecondActivity跳轉到FirstActivity時發現SecondActivity消失了,這就是singleTask的特點在這個跳轉過程中系統發現有存在的FirstActivity實例,於是不再生成新的實例,而是將FirstActivity之上的Activity實例統統出棧,將FirstActivity變為棧頂對象,顯示到幕前。
singleTask模式的特點:如果發現有對應的Activity實例,則使此Activity實例之上的其他Activity實例統統出棧,使此Activity實例成為棧頂對象,顯示到幕前。
Activity在同一個Task內只有一個實例. 當系統采用singleTask模式加載Activity時,又分為以下三種情況:
(1)如果將要啟動的Activity不存在,那麼系統將會創建該實例,並將其加入Task棧頂
(2)如果將要啟動的Activity已存在,且存在棧頂,那麼此時與singleTop模式的行為相同
(3)如果將要啟動的Activity存在但是沒有位於棧頂,那麼 此時系統會把位於該Activity上面的所有其他Activity全部移出Task,從而使得該目標Activity位於棧頂
4.singleInstance(全局單例模式)
這種模式是四種模式中最難理解的一種模式,因為這種模式會重新創建一個新的任務棧,將Activity放置於這個棧中,並保證其它的Activity不再進入,由於這種模式比較復雜,我們首先來說說它的原理,然後再結合實例進一步的理解,假如現在用戶打開了兩個應用分別為應用1和應用2,應用1和應用2的任務棧假如如下圖左邊,此時在應用1中想打開Activity3,這時應用1和應用2就會共享Activity3的引用,
注意:之所以能公用Activity的引用是以應用2中的Activity設置了LaunchMode=singleInstance為前提的。
由於這種模式比較復雜,我們舉兩個不同例子,來說明不同的問題
舉例一、
還是上面的兩個Activity。FirstActivity和SecondActivity在兩個Activityt跳轉的過程中我們打印兩個Activity所在的任務棧的ID
對以上兩個Activity做如下修改,並且把SecondActivity的啟動模式改為singleInstance
tv_showViewClass=(TextView) findViewById(R.id.tv_showViewClass);
tv_showViewClass.setText(當前Activity:+ +this.toString()+ +當前TaskId:+this.getTaskId());啟動後和點擊跳轉按鈕後的界面如下
我們發現兩個Activity的TaskId是不同的,說明這兩個Activity是位於不同的任務棧中的,從而證實了為SecondActivity重新建立了一個任務棧,可能有的朋友會問,在這個時候如果點擊返回按鈕它們是怎麼出棧的呢?假如現在我們點擊返回按鈕它的任務棧的變化如下圖
假如我們在SecondActivity中點擊按鈕跳轉到FirstActivity然後會以怎樣的方式退出應用呢?此時 它的任務棧的變化如下
圖中下半部分顯示的在SecondActivity中再次跳轉到FirstActivity,這個時候系統會在原始棧結構中生成一個FirstActivity實例,然後回退兩次,注意,並沒有退出,而是回到了SecondActivity,為什麼呢?是因為從SecondActivity跳轉到FirstActivity的時候,我們的起點變成了SecondActivity實例所在的棧結構,這樣一來,我們需要“回歸”到這個棧結構。
由於singleInstance比較復雜些,我們再來舉一個兩個應用的例子為了和上面的例子混淆,我們重新寫兩個應用
第一個App中有兩個Activity分別為Activity1和ShareActivity
第二個App中有一個Activity2我們在這個App中啟動第一個App的ShareActivity
第一個App的Activity源碼如下
package com.example.activitylauchmodepractice; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class Activity1 extends Activity { private Button btn_jumpToSecondActivity; private TextView tv_showViewClass; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first); tv_showViewClass=(TextView) findViewById(R.id.tv_showViewClass); tv_showViewClass.setText(當前Activity:+ +this.toString()+ +當前TaskId:+this.getTaskId()); btn_jumpToSecondActivity=(Button) findViewById(R.id.btn_jumpToSharedActivity); btn_jumpToSecondActivity.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(Activity1.this,ShareActivity.class); startActivity(intent); } }); } }ShareActivity源碼
package com.example.activitylauchmodepractice; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class ShareActivity extends Activity { private Button btn_jump; private TextView tv_showViewClass; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); tv_showViewClass=(TextView) findViewById(R.id.tv_showViewClass); tv_showViewClass.setText(當前Activity:+ +this.toString()+ +當前TaskId:+this.getTaskId()); } }
package com.example.singleinstancepractice; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { private Button btn_jump; private TextView tv_showTaskId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_showTaskId=(TextView) findViewById(R.id.tv_showTaskId); tv_showTaskId.setText(當前Activity:+ +this.toString()+ +當前TaskId:+this.getTaskId()); btn_jump=(Button) findViewById(R.id.btn_jump); btn_jump.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent =new Intent(); intent.setAction(SecondActivity_action); startActivity(intent); } }); } }當我們在第一個App中打開ShareActivity後再按後退鍵回到原來界面時,ShareActivity做為一個獨立的個體存在,如果這時我們在第二個App中打開ShareActivity無需創建新的ShareActivity實例即可看到結果,因為系統會自動查找,存在則直接利用。原理圖如下:
注意:上圖是建立在第一個App運行到手機上時點擊第二個App上的跳轉按鈕跳轉到ShareActivity的情況的基礎上的變化過程。
集成地圖SDK國內常用的地圖SDK就是百度和高德了,二者的用法大同小異,可按照官網上的開發指南一步步來。下面是我在集成地圖SDK時遇到的問題說明:1、點擊基本地圖功能選項
之前我們說到了關於IQ聊天軟件的局域網聊天測試,今天給大伙說說氣泡的生成和編碼,這不是第三方的東西,是自己 開發的,需要整合布局和容器來實現,其實當你看到源碼後,就會覺得
Android 手機無法連接mac解決辦法一般的android連接mac 很方便不用安裝驅動就可以啦,可是不知道為什麼二般情況下有的android手機(小米2,華為等)就
前言別看本文看上去很簡單,實際在實驗過程中遇到了很多問題,比如andorid studio下ndk編譯報錯,而本文呈現給大家的都是最終可行的方法.所需資源bzip2 bs