Author:ProZoom
Hobby:愛折騰、愛思考,想靜靜的ProZoom
Github --- 簡書 --- CSDN --- 關(guān)于我
1 創(chuàng)建表示層(Activity)
1.1定義Activity ,繼承Activity
在AndroidManifest.xml的<application>節(jié)點(diǎn)中聲明<activity>
<activity
android:name="com.itheima.intent.SecondActivity"
android:label="@string/title_activity_second" >
//這兩句可以指定手機(jī)home里所是否顯示的程序圖標(biāo)
</activity >
1.2顯式意圖創(chuàng)建方式
構(gòu)造函數(shù),代碼少
startActivity(new Intent( this,SecondActivity.class));
類名形式,靈活,可擴(kuò)展性強(qiáng)
intent.setClassName(this, "cn.itcast.activity.NewActivity");
包名類名形式,可啟動(dòng)其他程序中的Activity
intent.setClassName("cn.itcast.downloader", "cn.itcast.downloader.MainActivity");
1.3 創(chuàng)建Activity并傳遞數(shù)據(jù)
在意圖對(duì)象中封裝了一個(gè)Bundle對(duì)象,可以用來攜帶數(shù)據(jù)
在新Activity中可以獲得意圖對(duì)象以獲取其中Bundle保存的數(shù)據(jù)
Intent intent = new Intent();
Bundle extras = new Bundle();
extras.putString("key", "value");
intent.putExtras(extras);
startActivity(intent);
1.4 創(chuàng)建Activity獲取返回?cái)?shù)據(jù)
使用startActivityForResult(Intent intent, int requestCode) 方法打開Activity
重寫onActivityResult(int requestCode, int resultCode, Intent data) 方法
新Activity中調(diào)用setResult(int resultCode, Intent data) 設(shè)置返回?cái)?shù)據(jù)之后,關(guān)閉Activity就會(huì)調(diào)用onActivityResult方法
Intent intent = new Intent();
intent.putExtra("key", "value");
intent.setClassName(this, "cn.itcast.activity.NewActivity" );
startActivityForResult(intent,100);
------------------------------------------------
@Override
/**
* requestCode 請(qǐng)求碼
* resultCode 響應(yīng)碼
* data 返回?cái)?shù)據(jù)
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//設(shè)置返回?cái)?shù)據(jù)之后,關(guān)閉Activity就會(huì)調(diào)用onActivityResult方法
}
1.5 隱式意圖創(chuàng)建Activity
顯式意圖是指在創(chuàng)建意圖時(shí)指定了組件,而隱式意圖則不指定組件,通過動(dòng)作、類型、數(shù)據(jù)匹配對(duì)應(yīng)的組件
在清單文件中定義<activity>時(shí)需要定義<intent-filter>才能被隱式意圖啟動(dòng)
<intent-filter>中至少配置一個(gè)<action>和一個(gè)<category>,否則無法被啟動(dòng)
Intent對(duì)象中設(shè)置的action、category、data在<intent-filter>必須全部包含才能啟動(dòng)
<intent-filter>中的<action>、<category>、<data>都可以配置多個(gè),Intent對(duì)象中不用全部匹配,每樣匹配一個(gè)即可啟動(dòng)
如果一個(gè)意圖可以匹配多個(gè)Activity,Android系統(tǒng)會(huì)提示選擇
<activity
android:name="com.itheima.intent.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Intent intent = new Intent(this,SecondActivity.class);
intent.setAction( Intent.ACTION_APP_ERROR);
startActivity(intent);
1.6 手動(dòng)退出當(dāng)前Activity
調(diào)用finish()方發(fā),可以復(fù)寫此方法,自定義按返回鍵所發(fā)生的事件。
2 生命周期
2.1 Acitivity三種存活狀態(tài)
Active 運(yùn)行:activity在最前端運(yùn)行,處于屏幕前景(當(dāng)前task的棧頂Activity處于Active狀態(tài)),同一時(shí)刻只能有一個(gè)Activity處于Active狀態(tài)。
Stopped 停止:activity不可見,完全被覆蓋,但依然保持所有的狀態(tài)和內(nèi)存信息。
Paused 暫停:activity可見,但前端還有其他activity,處于背景畫面畫面狀態(tài),失去了焦點(diǎn),但依然是活動(dòng)狀態(tài)。
2.2 Activity的生命周期可以分為三組
完整的生命周期 oncreate - onstart - onresume - onpause - onstop - ondestroy
可視生命周期 onstart - onresume - onpause - onstop - onstart - onresume
前臺(tái)生命周期 onresume - onpause
2.3各種狀態(tài)之間通過下列的方法調(diào)用轉(zhuǎn)換
onCreate:創(chuàng)建時(shí)調(diào)用,或者程序在暫停、停止?fàn)顟B(tài)下被殺死之后重新打開時(shí)也會(huì)調(diào)用。在activity第一次被創(chuàng)建的時(shí)候調(diào)用。這里是你做所有初始化設(shè)置的地方──創(chuàng)建視圖、設(shè)置布局、綁定數(shù)據(jù)至列表等。如果曾經(jīng)有狀態(tài)記錄(參閱后述Saving Activity State。),則調(diào)用此方法時(shí)會(huì)傳入一個(gè)包含著此activity以前狀態(tài)的包對(duì)象做為參數(shù)。
onDestroy:銷毀時(shí)調(diào)用,在activity銷毀前調(diào)用。這是activity接收的最后一個(gè)調(diào)用。這可能發(fā)生在activity結(jié)束(調(diào)用了它的 finish() 方法)或者因?yàn)橄到y(tǒng)需要空間所以臨時(shí)的銷毀了此acitivity的實(shí)例時(shí)。你可以用isFinishing() 方法來區(qū)分這兩種情況。
onStart:當(dāng)activity正要變得為用戶所見時(shí)被調(diào)用,
onStop:進(jìn)入停止?fàn)顟B(tài),或者銷毀時(shí)會(huì)調(diào)用,當(dāng)activity不再為用戶可見時(shí)調(diào)用此方法。這可能發(fā)生在它被銷毀或者另一個(gè)activity(可能是現(xiàn)存的或者是新的)回到運(yùn)行狀態(tài)并覆蓋了它。
onResume:onStart之后或者從暫停狀態(tài)恢復(fù)時(shí)調(diào)用,從停止?fàn)顟B(tài)恢復(fù)時(shí)由于調(diào)用onStart,也會(huì)調(diào)用onResume,在activity開始與用戶進(jìn)行交互之前被調(diào)用。此時(shí)activity位于堆棧頂部,并接受用戶輸入。
onPause:進(jìn)入暫停、停止?fàn)顟B(tài),或者銷毀時(shí)會(huì)調(diào)用,當(dāng)系統(tǒng)將要啟動(dòng)另一個(gè)activity時(shí)調(diào)用。此方法主要用來將未保存的變化進(jìn)行持久化,停止類似動(dòng)畫這樣耗費(fèi)CPU的動(dòng)作等。這一切動(dòng)作應(yīng)該在短時(shí)間內(nèi)完成,因?yàn)橄乱粋€(gè)activity必須等到此方法返回后才會(huì)繼續(xù)。
onRestart:從停止?fàn)顟B(tài)恢復(fù)時(shí)調(diào)用,在activity執(zhí)行onStop()停止后,在再次啟動(dòng)之前被調(diào)用。
總以onStart()繼之。

2.4 保存信息的方法
onSaveInstanceState:在Activity被動(dòng)的摧毀或停止的時(shí)候調(diào)用,用于保存運(yùn)行數(shù)據(jù),可以將數(shù)據(jù)存在在Bundle中
onRestoreInstanceState:該方法在Activity被重新繪制的時(shí)候調(diào)用,例如改變屏幕方向,savedInstanceState為onSaveInstanceState保存的數(shù)據(jù)
2.5 Activity生命周期總結(jié)
1,Activity運(yùn)行時(shí)按下HOME鍵(跟被完全覆蓋是一樣的):onSaveInstanceState --> onPause --> onStop onRestart -->onStart--->onResume
2,Activity未被完全覆蓋只是失去焦點(diǎn):onPause--->onResume
3,當(dāng)前Activity產(chǎn)生事件彈出Toast和AlertDialog的時(shí)候Activity的生命周期不會(huì)有改變
3 啟動(dòng)模式
activity的任務(wù)棧的概念:
activity task stack
activity stack
back stack 后退棧
在Android系統(tǒng)中我們創(chuàng)建的Acitivity是以棧的形式呈現(xiàn)的
Actvity的啟動(dòng)模式
在AndroidManifest.xml中的<activity>標(biāo)簽中可以配置android:launchMode屬性,用來控制Actvity的啟動(dòng)模式
<activity
android:launchMode="singleInstance"
android:name="com.itheima.mode.A_Activity"
android:label="14.A_Activity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:launchMode="singleInstance"
android:name="com.itheima.mode.B_Activity"
android:label="14.B_Activity" >
</activity>
Activity有四種加載模式:
standard、singleTop、singleTask、singleInstance(其中前兩個(gè)是一組、后兩個(gè)是一組),默認(rèn)為standard
standard:就是intent將發(fā)送給新的實(shí)例,所以每次跳轉(zhuǎn)都會(huì)生成新的activity。
singleTop:也是發(fā)送新的實(shí)例,但不同standard的一點(diǎn)是,在請(qǐng)求的Activity正好位于棧頂時(shí)(配置成singleTop的Activity),不會(huì)構(gòu)造新的實(shí)例
singleTask:和后面的singleInstance都只創(chuàng)建一個(gè)實(shí)例,當(dāng)intent到來,需要?jiǎng)?chuàng)建設(shè)置為singleTask的Activity的時(shí)候,系統(tǒng)會(huì)檢查棧里面是否已經(jīng)有該Activity的實(shí)例。如果有直接將intent發(fā)送給它。
singleInstance:首先說明一下task這個(gè)概念,Task可以認(rèn)為是一個(gè)棧,可放入多個(gè)Activity。比如啟動(dòng)一個(gè)應(yīng)用,那么Android就創(chuàng)建了一個(gè)Task,然后啟動(dòng)這個(gè)應(yīng)用的入口Activity,那在它的界面上調(diào)用其他的Activity也只是在這個(gè)task里面。那如果在多個(gè)task中共享一個(gè)Activity的話怎么辦呢。舉個(gè)例來說,如果開啟一個(gè)導(dǎo)游服務(wù)類的應(yīng)用程序,里面有個(gè)Activity是開啟GOOGLE地圖的,當(dāng)按下home鍵退回到主菜單又啟動(dòng)GOOGLE地圖的應(yīng)用時(shí),顯示的就是剛才的地圖,實(shí)際上是同一個(gè)Activity,實(shí)際上這就引入了singleInstance。singleInstance模式就是將該Activity單獨(dú)放入一個(gè)棧中,這樣這個(gè)棧中只有這一個(gè)Activity,不同應(yīng)用的intent都由這個(gè)Activity接收和展示,這樣就做到了共享。當(dāng)然前提是這些應(yīng)用都沒有被銷毀,所以剛才是按下的HOME鍵,如果按下了返回鍵,則無效
//可以有多個(gè)A
standard:每次調(diào)用startActivity()啟動(dòng)時(shí)都會(huì)創(chuàng)建一個(gè)新的Activity放在棧頂
singleTop:啟動(dòng)Activity時(shí),指定Activity不在棧頂就創(chuàng)建,如在棧頂,則不再創(chuàng)建
//單例的,不能使用返回?cái)?shù)據(jù)方法
singleTask:如果啟動(dòng)的Activity不存在就創(chuàng)建,如果存在直接跳轉(zhuǎn)到指定的Activity所在位置
singleInstance:如果啟動(dòng)的Activity不存在就創(chuàng)建,如果存在就將指定的Activity移動(dòng)到棧頂
6 android推出activity的方式總結(jié)
在android中使用:[activityname].this.finish(); 只是退出了activity的堆棧中,要真正的退出程序在手機(jī)cpu中的運(yùn)行,當(dāng)應(yīng)用不再使用時(shí),通常需要關(guān)閉應(yīng)用,可以使用以下三種方法關(guān)閉android應(yīng)用:
一 使用killProcess()函數(shù),首先獲取當(dāng)前進(jìn)程的id,然后殺死該進(jìn)程:
android.os.Process.killProcess(android.os.Process.myPid());
通過這種方式不能將應(yīng)用程序完全殺死,并且他不會(huì)把當(dāng)前應(yīng)用應(yīng)用的Activity的task任務(wù)棧清空
二 在activity的生命周期函數(shù)中添加如下的函數(shù),強(qiáng)制關(guān)閉與該包有關(guān)聯(lián)的一切執(zhí)行:
ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE);
am.restartPackage("packagename");
或殺死 am.killBackgroundProcesses(info.getPackname());
還需要在AndroidManifest.xml文件中加入如下的權(quán)限:<uses-permission android:name="android.permission.RESTART_PACKAGES" />
此做法:只能殺死別人,不能殺死自己
三、 終止當(dāng)前正在運(yùn)行的Java虛擬機(jī),導(dǎo)致程序終止
System.exit(0);
不會(huì)把自己的應(yīng)用程序殺死
企業(yè)中做法:
創(chuàng)建類app 繼承Application
AndroidMainfest -->name -->app //聲明該類為整個(gè)應(yīng)用程序全局的實(shí)例
創(chuàng)建整個(gè)應(yīng)用程序全局的實(shí)例
App.class:
ArrayList<Activity> activities;
其他的Activity中:
public void onCreate(Bundle savedInstanceState) {
App app = (App) getApplication();//獲取應(yīng)用程序全局的實(shí)例引用
app.activities.add(this); //把當(dāng)前Activity放入集合中
}
public void onDestory(){
App app = (App) getApplication();//獲取應(yīng)用程序全局的實(shí)例引用
app.activities.remove(this); //把當(dāng)前Activity從集合中移除
}
安全退出:
在菜單退出按鈕的事件中定義如下代碼:
App app = (App) getApplication();
List<Activity> activities = app.activities;
for(Activity act:activities){
act.finish();//顯式結(jié)束
}
2.3以后應(yīng)用不能完全退出,被屏蔽了。怎樣完全退出呢?
由于android 是 基于liux 操作系統(tǒng)的, 所以 一般情況下 我們 使用
android.os.Process.killProcess(android.os.Process.myPid()); 這個(gè)方法就可以殺掉進(jìn)程,
不過當(dāng) activity 多的時(shí)候,而且當(dāng)我們忘記finish 其中的某幾個(gè),或者說,你對(duì) AndroidMainfest.xml 中的 每個(gè) Activity 中 android:launchMode , android:alwaysRetainTaskState 這些都不是很清楚時(shí),就會(huì)出現(xiàn) 應(yīng)用的 關(guān)閉不完全,主要原因是由于 殘留的 Activity 本身是一個(gè)進(jìn)程,所以系統(tǒng)又把這個(gè)Activity提到了最前面,就會(huì)使我們的程序沒有完全關(guān)閉,
那么 再 1.5---2.1 用了一個(gè) 方法,都可以成功的解決這個(gè)問題,那就是
final ActivityManager am = (ActivityManager) ACTIVITY
// .getSystemService(Context.ACTIVITY_SERVICE);
// am.restartPackage(ACTIVITY.getPackageName());
但是到了 2.2 的時(shí)候, 這個(gè)方法,就不奏效了, 那么我想請(qǐng)問 各位同仁們,有沒有 什么通用的辦法呢~~~~
這個(gè)問題,網(wǎng)上的童鞋,也是有非常多做法,android123 也給我們提供了,非常多的解決辦法, 但是小弟不才,他們提供的方法,有些時(shí)候,不管用,所以很費(fèi)腦~~~~
現(xiàn)在我將我 這個(gè)方法 分享給大家, 這個(gè)方法在 1.5--2.3 的機(jī)器上都測(cè)試過,是可以完全殺死進(jìn)程的
該方法需要兩個(gè)必要條件
條件一: 一個(gè)自己管理Activity 的列表, 網(wǎng)上很多用 ArryList 來存儲(chǔ)acitivity
條件二: 需要一段,重新開啟堆棧,跳轉(zhuǎn)到 Home界面,并且 用liux的殺掉進(jìn)程的方法
代碼如下
protected void quit()
{
int size = activityManager.activityStackCount();
for(int i =size-1 ; i > 0 ;i--)
{
Activity activity = activityManager.allTaskActivity().get(i);
activityManager.popActivity(activity);
}
activityManager = null;
getActivity().finish();
//目前最為通用的 關(guān)閉進(jìn)程的方法以后的版本使用
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
android.os.Process.killProcess(android.os.Process.myPid());
}
7 any tips
一些關(guān)于 Activity 的技巧
鎖定 Activity 運(yùn)行時(shí)的屏幕方向
Android 內(nèi)置了方向感應(yīng)器的支持。在 G1 中,Android 會(huì)根據(jù) G1 所處的方向自動(dòng)在豎屏和橫屏間切換。但是有時(shí)我們的應(yīng)用程序僅能在橫屏 / 豎屏?xí)r運(yùn)行,比如某些游戲,此時(shí)我們需要鎖定該 Activity 運(yùn)行時(shí)的屏幕方向,<activity >節(jié)點(diǎn)的 android:screenOrientation屬性可以完成該項(xiàng)任務(wù),示例代碼如下:
<activity android:name=".EX01"
android:label="@string/app_name"
android:screenOrientation="portrait">// 豎屏 , 值為 landscape 時(shí)為橫屏
…………
</activity>
全屏的 Activity
要使一個(gè) Activity 全屏運(yùn)行,可以在其 onCreate()方法中添加如下代碼實(shí)現(xiàn):
// 設(shè)置全屏模式
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 去除標(biāo)題欄
requestWindowFeature(Window.FEATURE_NO_TITLE);
在 Activity 的 Title 中加入進(jìn)度條
為了更友好的用戶體驗(yàn),在處理一些需要花費(fèi)較長時(shí)間的任務(wù)時(shí)可以使用一個(gè)進(jìn)度條來提示用戶“不要著急,我們正在努力的完成你交給的任務(wù)”。如下圖:
在 Activity 的標(biāo)題欄中顯示進(jìn)度條不失為一個(gè)好辦法,下面是實(shí)現(xiàn)代碼:
// 不明確進(jìn)度條
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
setProgressBarIndeterminateVisibility(true);
// 明確進(jìn)度條
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.main);
setProgress(5000);