Activity活動(dòng)
描述:
1)表示用戶交互的一個(gè)界面(活動(dòng)),每一個(gè)activity對(duì)應(yīng)一個(gè)界面
2)是所有View的容器:button,textview,imageview;我們?cè)诮缑嫔峡吹降亩际且粋€(gè)個(gè)的view
3)有個(gè)ActivityManager的管理服務(wù)類,用于維護(hù)與管理Activity的啟動(dòng)與銷毀发乔;
Activity啟動(dòng)時(shí)辆毡,會(huì)把Activity的引用放入任務(wù)棧中
4)一個(gè)應(yīng)用程序可以被別的應(yīng)用程序的activity開啟
此時(shí),是將此應(yīng)用程序的引用加入到了開啟的那個(gè)activity的任務(wù)棧中了
5)activity是運(yùn)行在自己的程序進(jìn)程里面的
在一個(gè)應(yīng)用程序中涮俄,可以申請(qǐng)單獨(dú)的進(jìn)程夫偶,然此應(yīng)用程序中的一個(gè)組件在新的進(jìn)程中運(yùn)行
6)可以在activity里面添加permission標(biāo)簽,調(diào)用者必須加入這個(gè)權(quán)限
與錢打交道的界面界睁,都不允許被其他應(yīng)用程序隨意打開
如果覺得那個(gè)activity比較重要麸恍,可以在清單文件中配置蚕断,防止別人隨意打開,需要配置一個(gè)權(quán)限
自定義權(quán)限:
在清單文件中配置permission苞尝,創(chuàng)建一個(gè)新的權(quán)限
創(chuàng)建后说铃,就會(huì)在清單文件中生成這個(gè)權(quán)限了
此時(shí)杨赤,需要開啟這個(gè)界面,就需要使用這個(gè)權(quán)限
Tips:
*不可使用中文文本截汪,需要使用字符串,抽取出來
*聲明之后植捎,會(huì)在gen的目錄下衙解,多出來一個(gè)文件:Manifest的文件,系統(tǒng)也存在一個(gè)這樣的文件
1焰枢、創(chuàng)建Activity
1)定義類繼承自Activity類蚓峦;
2)在清單文件中Application節(jié)點(diǎn)中聲明節(jié)點(diǎn)舌剂;
2、啟動(dòng)Activity
通過意圖(Intent)來啟動(dòng)一個(gè)Activity暑椰;
1)顯示啟動(dòng):
顯示啟動(dòng)一般用于自己調(diào)用自己的情況(在當(dāng)前應(yīng)用找)霍转,這樣的啟動(dòng)方式比較快速,創(chuàng)建Intent后指定包名和類名一汽;
Intent intent = new Intent(this,OtherActivity.class);
startActivity(intent);//啟動(dòng)新的Activity
或者:
Intent intent = new Intent();
intent.setClassName("com.itheima.activity","com.itheima.activity.OtherActivity");//包名避消、全類名
startActivity(intent);//啟動(dòng)新的Activity
2)隱式啟動(dòng):
一般用于調(diào)用別人的Activity,創(chuàng)建Intent后指定動(dòng)作和數(shù)據(jù)以及類型召夹;
//電話
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);//設(shè)置動(dòng)作
intent.setData(Uri.parse("tel://123456"));//設(shè)置數(shù)據(jù)
//網(wǎng)頁
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://192.168.1.45:8080/androidWeb"));
//音頻/視頻岩喷,設(shè)置type
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///mnt/sdcard/daqin.mp3"),"audio/*");//設(shè)置數(shù)據(jù)和數(shù)據(jù)類型,將啟動(dòng)音頻播放器(vedio)
3)為隱式啟動(dòng)配置意圖過濾器:
顯式意圖是指在創(chuàng)建意圖時(shí)指定了組件监憎,而隱式意圖則不指定組件纱意,通過動(dòng)作、類型鲸阔、數(shù)據(jù)匹配對(duì)應(yīng)的組件偷霉;
在清單文件中定義時(shí)需要定義才能被隱式意圖啟動(dòng);
中至少配置一個(gè)和一個(gè)褐筛,否則無法被啟動(dòng)类少;
Intent對(duì)象中設(shè)置的action、category死讹、data在必須全部包含Activity才能啟動(dòng)瞒滴;
中的、赞警、都可以配置多個(gè)妓忍,Intent對(duì)象中不用全部匹配,每樣匹配一個(gè)即可啟動(dòng)愧旦;
如果一個(gè)意圖可以匹配多個(gè)Activity世剖,Android系統(tǒng)會(huì)提示選擇;
3旁瘫、啟動(dòng)時(shí)傳遞數(shù)據(jù)
可通過意圖Intent對(duì)象實(shí)現(xiàn)Activity之間的數(shù)據(jù)傳遞;
使用Intent.putExtra()方法裝入一些數(shù)據(jù),被啟動(dòng)的Activity可在onCreate方法中g(shù)etIntent()獲惹眚恰酬凳;
可傳輸?shù)臄?shù)據(jù)類型: a.基本數(shù)據(jù)類型(數(shù)組),b. String(數(shù)組),c. Bundle(Map),d. Serializable(Bean), e.Parcelable(放在內(nèi)存一個(gè)共享空間里);
基本類型:
Intent intent = new Intent(this,OtherActivity.class);
intent.putExtra("name", "張飛");????????????? //攜帶數(shù)據(jù)
intent.putExtra("age", 12);
startActivity(intent);
一捆數(shù)據(jù):
Intent intent = new Intent(this,OtherActivity.class);
Bundle b1 = new Bundle();
b1.putString("name", "趙云");
b1.putInt("age", 25);
Bundle b2 = new Bundle();
b2.putString("name", "關(guān)羽");
b2.putInt("age", 44);
intent.putExtra("b1", b1);
intent.putExtra("b2", b2);
序列化對(duì)象(須實(shí)現(xiàn)序列化接口):
Intent intent = new Intent(this,OtherActivity.class);
Person p = new Person("張遼", 44);
intent.putExtra("p", p);
接收數(shù)據(jù):
在OtherActivity的onCreate()方法,通過getIntent().get相關(guān)的數(shù)據(jù)的方法來獲取數(shù)據(jù)遭庶;
4宁仔、關(guān)閉時(shí)返回?cái)?shù)據(jù)
基本流程:
使用startActivityForResult(Intentintent,intrequestCode)方法打開Activity;
重寫onActivityResult(intrequestCode,intresultCode, Intent data)方法峦睡;
新Activity中調(diào)用setResult(intresultCode, Intent data)設(shè)置返回?cái)?shù)據(jù)之后翎苫,關(guān)閉Activity就會(huì)調(diào)用上面的onActivityResult方法权埠;
注意:新的Activity的啟動(dòng)模式不能設(shè)置成singleTask(如果已創(chuàng)建,會(huì)使用以前創(chuàng)建的)與singleInstance(單例煎谍,單獨(dú)的任務(wù)棧)攘蔽,
不能被摧毀(執(zhí)行不到finish方法),父Activity中的onActivityResult方法將不會(huì)執(zhí)行呐粘;
finish():表示關(guān)閉當(dāng)前Activity满俗,會(huì)調(diào)用onDestroy方法;
Activity_A:
public void openActivityB(View v) {
Intent intent = new Intent(this, Activity_B.class);
Person p = new Person("張遼", 44);
intent.putExtra("p", p);
startActivityForResult(intent,100);//此方法事哭,啟動(dòng)新的Activity漫雷,等待返回結(jié)果,結(jié)果一旦返回,自動(dòng)執(zhí)行onActivityResult()方法
}
protected void onActivityResult(intrequestCode, int resultCode, Intent data) {
if(data == null) {//沒有數(shù)據(jù)鳍咱,不執(zhí)行
return;
}
System.out.println(requestCode +", " + resultCode);//code可用來區(qū)分降盹,哪里返回的數(shù)據(jù)
String name =data.getStringExtra("name");
int age =data.getIntExtra("age", -1);
}
Activity_B:
public void close(View v) {
// ==關(guān)閉當(dāng)前Activity時(shí),設(shè)置返回的數(shù)據(jù)==
Intent intent = new Intent();
intent.putExtra("name","典韋");
intent.putExtra("age",55);
setResult(200, intent);
finish();//關(guān)閉谤辜,類似于點(diǎn)擊了后退
}
5蓄坏、生命周期
1)Acitivity三種狀態(tài)
a.運(yùn)行:activity在最前端運(yùn)行;
b.停止:activity不可見,完全被覆蓋;
c.暫停:activity可見丑念,但前端還有其他activity<>涡戳,注意:在當(dāng)前Activitiiy彈出的對(duì)話框是Activity的一部分,彈出時(shí)脯倚,不會(huì)執(zhí)行onPause方法渔彰;
2)生命周期相關(guān)的方法(都是系統(tǒng)自動(dòng)調(diào)用,都以on開頭):
a.onCreate:創(chuàng)建時(shí)調(diào)用推正,或者程序在暫停恍涂、停止?fàn)顟B(tài)下被殺死之后重新打開時(shí)也會(huì)調(diào)用;
b.onStart:onCreate之后或者從停止?fàn)顟B(tài)恢復(fù)時(shí)調(diào)用植榕;
c.onResume:onStart之后或者從暫停狀態(tài)恢復(fù)時(shí)調(diào)用再沧,從停止?fàn)顟B(tài)恢復(fù)時(shí)由于調(diào)用onStart,也會(huì)調(diào)用onResume(界面獲得焦點(diǎn))尊残;
d.onPause:進(jìn)入暫停炒瘸、停止?fàn)顟B(tài),或者銷毀時(shí)會(huì)調(diào)用(界面失去焦點(diǎn))寝衫;
e.onStop:進(jìn)入停止?fàn)顟B(tài)顷扩,或者銷毀時(shí)會(huì)調(diào)用;
f.onDestroy:銷毀時(shí)調(diào)用慰毅;
g.onRestart:從停止?fàn)顟B(tài)恢復(fù)時(shí)調(diào)用屎即;
3)生命周期圖解:
應(yīng)用啟動(dòng)時(shí),執(zhí)行onCreate onStart onResume,退出時(shí)執(zhí)行:onPause onStop onDestroy;
6、橫豎屏切換與信息的保存恢復(fù)
切換橫豎屏?xí)r技俐,會(huì)自動(dòng)查找layout-port、layout-land中的布局文件统台,默認(rèn)情況下雕擂,
切換時(shí),將執(zhí)行摧毀onPause onStop
onDestroy贱勃,再重置加載新的布局onCreate onStart
onResume井赌;
切換時(shí)如果要保存數(shù)據(jù),可以重寫: onSaveInstanceState();
恢復(fù)數(shù)據(jù)時(shí),重寫: onRestoreInstanceState();
固定橫屏或豎屏:android:screenOrientation="landscape"
橫豎屏切換,不摧毀界面(程序繼續(xù)執(zhí)行)android:configChanges="orientation|keyboardHidden|screenSize"
保存信息狀態(tài)的相關(guān)方法:
a.onSaveInstanceState:
在Activity被動(dòng)的摧毀或停止的時(shí)候調(diào)用(如橫豎屏切換,來電),用于保存運(yùn)行數(shù)據(jù)贵扰,可以將數(shù)據(jù)存在在Bundle中仇穗;
b.onRestoreInstanceState:
該方法在Activity被重新繪制的時(shí)候調(diào)用,例如改變屏幕方向戚绕,onSavedInstanceState可為onSaveInstanceState保存的數(shù)據(jù)
7纹坐、啟動(dòng)模式
1)任務(wù)棧的概念
問:一個(gè)手機(jī)里面有多少個(gè)任務(wù)棧?
答:一般情況下舞丛,有多少個(gè)應(yīng)用正在運(yùn)行耘子,就對(duì)應(yīng)開啟多少個(gè)任務(wù)棧;
一般情況下球切,每開啟一個(gè)應(yīng)用程序就會(huì)創(chuàng)建一個(gè)與之對(duì)應(yīng)的任務(wù)棧谷誓;
二般情況下,如launchMode為singleInstance吨凑,就創(chuàng)建自己?jiǎn)为?dú)的任務(wù)棧捍歪;
2)任務(wù)棧的作用:
它是存放Activity的引用的,Activity不同的啟動(dòng)模式鸵钝,對(duì)應(yīng)不同的任務(wù)棧的存放糙臼;
可通過getTaskId()來獲取任務(wù)棧的ID,如果前面的任務(wù)棧已經(jīng)清空蒋伦,新開的任務(wù)棧ID+1弓摘,是自動(dòng)增長(zhǎng)的;
3)啟動(dòng)模式:
在AndroidManifest.xml中的標(biāo)簽中可以配置android:launchMode屬性痕届,用來控制Actvity的啟動(dòng)模式韧献;
在Android系統(tǒng)中我們創(chuàng)建的Acitivity是以棧的形式呈現(xiàn)的:
①、standard:默認(rèn)的研叫,每次調(diào)用startActivity()啟動(dòng)時(shí)都會(huì)創(chuàng)建一個(gè)新的Activity放在棧頂锤窑;
②、singleTop:?jiǎn)?dòng)Activity時(shí)嚷炉,指定Activity不在任務(wù)棧棧頂就創(chuàng)建渊啰,如在棧頂,則不會(huì)創(chuàng)建,會(huì)調(diào)用onNewInstance()绘证,復(fù)用已經(jīng)存在的實(shí)例
③隧膏、singleTask:在任務(wù)棧里面只允許一個(gè)實(shí)例,如果啟動(dòng)的Activity不存在就創(chuàng)建嚷那,如果存在直接跳轉(zhuǎn)到指定的Activity所在位置胞枕,
如:棧內(nèi)有ABCD,D想創(chuàng)建A,即A上的BCD相應(yīng)的Activity將移除魏宽;
④腐泻、singleInstance:(單例)開啟一個(gè)新的任務(wù)棧來存放這個(gè)Activity的實(shí)例,在整個(gè)手機(jī)操作系統(tǒng)里面只有一個(gè)該任務(wù)棧的實(shí)例存在队询,此模式開啟的Activity是運(yùn)行在自己?jiǎn)为?dú)的任務(wù)棧中的派桩;
4)應(yīng)用程序、進(jìn)程蚌斩、任務(wù)棧的區(qū)別
①铆惑、應(yīng)用程序:
四大組件的集合
在清單文件中都放在application節(jié)點(diǎn)下
對(duì)于終端用戶而言,會(huì)將其理解為activity
②凳寺、進(jìn)程:
操作系統(tǒng)分配的獨(dú)立的內(nèi)存空間鸭津,一般情況下,一個(gè)應(yīng)用程序會(huì)對(duì)應(yīng)一個(gè)進(jìn)程肠缨,特殊情況下逆趋,會(huì)有多個(gè)進(jìn)程
一個(gè)應(yīng)用程序會(huì)對(duì)應(yīng)一個(gè)或多個(gè)進(jìn)程
③、任務(wù)棧:task stack(back stack)后退棧
記錄用戶的操作步驟晒奕,維護(hù)用戶的操作體驗(yàn)闻书,
專門針對(duì)于activity而言的,只用于activity
一般使用standard脑慧,其他情況用別的
5)啟動(dòng)模式的演示
1魄眉、創(chuàng)建兩個(gè)activity,布局中設(shè)置兩個(gè)按鈕闷袒,分別開啟兩個(gè)activity
第一坑律、standard啟動(dòng)模式的:開啟幾個(gè)就會(huì)在任務(wù)棧中存在幾個(gè)任務(wù)
01和02都是存在于一個(gè)任務(wù)棧中的
第二、在清單文件中將02的啟動(dòng)模式改為singletop囊骤,
此時(shí)02處于棧頂晃择,就只會(huì)創(chuàng)建一個(gè)02的任務(wù),再開啟02也物,也不會(huì)創(chuàng)建新的
第三宫屠、將02的啟動(dòng)模式改為singletask
如果02上面有其他任務(wù)棧,就會(huì)將其他的清除掉滑蚯,利用這個(gè)已經(jīng)創(chuàng)建的02
當(dāng)開啟02的時(shí)候浪蹂,即先將01清除抵栈,然后利用下面的02
第四、將02的啟動(dòng)模式改為singleinstance
可以通過打印任務(wù)棧的id(調(diào)用getTaskId()方法)得知坤次,兩個(gè)activity不在同一個(gè)任務(wù)棧中
若先開啟三個(gè)01古劲,在開啟02,任務(wù)棧如圖:
再開啟01缰猴,任務(wù)棧的示意圖如下:
此時(shí)按返回鍵绢慢,會(huì)先一層一層清空01,最后再清空02
空進(jìn)程:任務(wù)棧清空洛波,意味著程序退出了,但進(jìn)程留著骚露,這個(gè)就是空進(jìn)程蹬挤,容易被系統(tǒng)回收;
8棘幸、內(nèi)存管理
Android系統(tǒng)在運(yùn)行多個(gè)進(jìn)程時(shí)焰扳,如果系統(tǒng)資源不足,會(huì)強(qiáng)制結(jié)束一些進(jìn)程,優(yōu)先選擇哪個(gè)進(jìn)程來結(jié)束是有優(yōu)先級(jí)的误续。
會(huì)按照以下順序殺死:
①吨悍、空:進(jìn)程中沒有任何組件;
②蹋嵌、后臺(tái):進(jìn)程中只有停止?fàn)顟B(tài)的Activity育瓜;
③、服務(wù):進(jìn)程中有正在運(yùn)行的服務(wù)栽烂;
④躏仇、可見:進(jìn)程中有一個(gè)暫停狀態(tài)的Activity;
⑤腺办、前臺(tái):進(jìn)程中正在運(yùn)行一個(gè)Activity焰手;
Activity在退出的時(shí)候進(jìn)程不會(huì)銷毀,會(huì)保留一個(gè)空進(jìn)程方便以后啟動(dòng).但在內(nèi)存不足時(shí)進(jìn)程會(huì)被銷毀;
Activity中不要在Activity做耗時(shí)的操作,因?yàn)锳ctivity切換到后臺(tái)之后(Activity停止了),內(nèi)存不足時(shí),也容易被銷毀怀喉;