【
Android四大組件之一
主要用于與用戶進行交互,在一個App中可能存在零個或多個Activity
】
【
Activity創建:
創建的步驟:
1)? 定義一個類,繼承自Activity
2)? 在清單文件中進行注冊(先注冊,后使用)
Android的四大組件都必須要在清單文件中進行注冊
思考:
1)? 當在AndroidManifest.xml清單文件中,如果不設置默認啟動頁,會報錯嗎?
答:不會報錯,但是App就沒有啟動頁面
2)? 當在AndroidManifest.xml清單文件中,設置多個頁面都是默認啟動頁,會報錯嗎?如果不報錯,到底是執行哪個頁面呢?
答:不會報錯,如果設置了多個啟動頁面,那么在程序圖標的列表中就會生成多個啟動圖標,???? 點擊不同的啟動圖標都可以開啟應用程序,進入對應的頁面。
】
【
Acitivity的啟動
需要使用到Intent類,Intent不是Android四大組件之一,Intent,意圖,主要用于Android三大組件之間的通訊,是三大組件的橋梁。
PS:這里的三大組件是Activity、Service、BroadcastReceiver
Activity的關閉
1)? finnish方法
2)點擊返回按鈕(返回按鈕的點擊事件默認就是關閉當前的Activity,這個點擊事件是可以修改的。
】
Context.startActivity(Intent)
【
一個Android應用程序可以包含零或多個Activity,當應用程序具有多個Activity時,就可能需要從一個Activity跳轉到另一個Activity。在Android中,Activity之間的導航是通過Intent(意圖)來完成
Intent并不是Andorid應用的組件,但它是各組件之間通信的載體
Intent不僅僅可以用于同一個App內來傳遞“意圖”,也可以跨App
==Context,上下文環境(在這里就是指應用程序環境,封裝了當前應用程序的一些相關信息)
】
【
顯示意圖:需要明確指定需要啟動的組件名稱
new Intent(Context, Class)
intent.setClass(Context, Class)
intent.setClassName(Context, StringclassName)
intent.setClassName(String packageName,String className)
intent.setComponent(ComponentNamecomponent)
intent.setClass(this,SecondActivity.class);
startActivity(intent);
】
【
// 顯示意圖的演示,需要明確指定開啟的組件的類名
publicvoidopen03(View v) {
// 如果使用的是顯示意圖,那么啟動組件的時候就不會去使用意圖過濾器過濾
Intent intent =newIntent();
// 設置組件的信息
// 這里要注意:設置組件信息的api有很多,其實都是大同小異的
// intent.setClass(this, SecondActivity.class);
// intent.setClassName(this,"com.example.day06.activitybasic.SecondActivity");
// intent.setClassName(this.getPackageName(),"com.example.day06.activitybasic.SecondActivity");
ComponentName component =newComponentName(this, SecondActivity.class);
intent.setComponent(component);
startActivity(intent);
}
】
【
隱式意圖不需要明確指定需要啟動的組件的名稱,只需要給定啟動的組件的相關信息
所謂的相關系,比如:打電話、上網、發郵件
Intent.setAction(String)// action是一個任意的字符串,但是一般以包名.intent.行為命名,比如com.qianfeng.demo.intent.hit
Intent.setData(Uri)
Intent.addCategory(String)// 自定義的一般都是default類型,default類型可以不單獨設置(默認)
intent.setAction(String action)? //
new Intent(String action)
new Intent(String action, Uri uri)
Intent intent = new Intent()
intent.setAction(String action)
intent.setData(Uriuri)
intent.setAction(String action)
intent.setData(Uri uri)
意圖過濾器:
action
Action代表該Intent所要完成的一個抽象“動作”
一個Intent對象最多包含一個action
一個Activity可以定義多個action
Android本身提供了很多action供開發者使用
Action代表該Intent所要完成的一個抽象“動作”
一個Intent對象最多包含一個action
一個Activity可以定義多個action
Android本身提供了很多action供開發者使用
為Activity增加額外的附加類別信息
為Activity增加額外的附加類別信息
data
聲明數據的類型(mimeType)、約束(scheme)、主機名(host)、端口(port)、路徑(path)等
聲明數據的類型(mimeType)、約束(scheme)、主機名(host)、端口(port)、路徑(path)等
應用場景:開啟別的應用程序中的界面,系統需要查詢匹配的Activity,效率較低
】
【示例1:打開撥號界面
publicvoidopen01(View v) {
Intentintent =newIntent();
//如果使用的是隱式意圖,那么在意圖中就保存相關的信息(就是想做什么事情)
//打籃球(動作+數據)
//動作
intent.setAction(Intent.ACTION_DIAL);
//url:統一資源定位符http://www.baidu.com
//uri:統一資源標識符tel://110 person://zhangsan
intent.setData(Uri.parse("tel://110"));
//開啟一個界面,完成指定的操作
startActivity(intent);
}
示例二:自定義隱式視圖及過濾器
android:name="com.example.day06.activitybasic.SecondActivity"
android:label="界面2">
那么系統就會找到系統中的各個組件對用的意圖過濾器,
然后進行過濾,如果過濾通過就會開啟這個組件 -->
<actionandroid:name="com.example.day06.activitybasic.inetnt.hit"/>
<categoryandroid:name="android.intent.category.DEFAULT"/>
<dataandroid:scheme="person"/>
android:name="com.example.day06.activitybasic.ThirdActivity"
android:label="界面3">
"com.example.day06.activitybasic.inetnt.hit"/>
"android.intent.category.DEFAULT"/>
"person"/>
注意:兩個Activity設置了兩個同樣的過濾器
//開啟自己的隱式意圖,不需要指定Activity的類名
publicvoidopen02(View v){
Intent intent =newIntent();
//設置action
intent.setAction("com.example.day06activity01.inetnt.hit");
//設置類型(如果是默認的,可以不設置)
//intent.addCategory(Intent.CATEGORY_DEFAULT);
//設置Date
intent.setData(Uri.parse("person://zhangsan"));
}
效果圖:
】
1、顯示意圖:必須指定要激活的組件的完整包名和類名
(應用程序之間耦合在一起,一般是在激活自己應用中的組件時使用顯示意圖。
效率較高)
2、隱式意圖:只需要指定執行的動作和數據就可以
(好處:應用程序之間沒有耦合。一般在激活其他應用中的組件時使用隱式意圖。
缺點:效率較低)
程序設計原則:高內聚、低耦合。
什么時候使用這兩個Intent?
一般情況下,在開啟同一個應用程序內部的組件會使用顯示意圖,相反,如果要開啟其他應用程序中的組件,一般使用隱式意圖。
】
【
1、Intent.setData(Uri)——> intent.getData():傳遞簡單的文本數據,// 傳遞Uri對象(實際上就是一個字符串)
2、putExtra(name ,value)——>? getXXXExtra()//傳遞額外數據
通過該方法可以傳遞以下數據類型:
八種基本數據類型
數組
字符串
序列化對象
(在Android中有兩個序列化接口:
A)Serializable接口: JDK自帶的接口,使用方式很簡單,只需要讓自定義類實現Serializable接口即可。
b)Parcelable接口,Android SDK提供的接口
相對于Serializable接口,序列化和反序列化的效率更高,是Android推薦使用的,但是序列化和反序列的部分操作需要程序員自己完成
Bundle對象,就是一個容器,操作和Map集合類似,是以鍵值對的方式存儲
3、putExtras(Bundle extras)——> getExtras():可以傳遞一組數據(Map集合)
4、putXXXArrayListExtra傳遞ArrayList對象
】
【
快捷鍵:ctrl+shift+o????? 優化導包
開啟Activity并獲取返回值
實現步驟:
1)在Activity01中調用startActivityForResult(inetnt,requestCode)方法,開啟一個指定的Activity
intent:意圖對象,用于開啟指定的Activity
requestCode:請求碼,用于區分被開啟的Activity
2)在Activity02中通過setResult(resultCode,intent)方法設置返回結果
resultCode:返回碼,用于表示返回值的狀態(操作成功:Activity.RESULT_OK)
intent:意圖對象,用于封裝返回結果
設置完結果之后關閉Activity02,當Ativity02被關閉后會自動將結果返回給開啟他的組件(Activty01)
3)在Activity01中改寫onActivityResult(intrequestCode, int resultCode, Intent data)方法,用于處理返回結果
requestCode,請求碼
resultCode,返回碼(結果碼)
data,Intent對象,封裝了返回的數據
注意:在處理結果的時候通常都需要先對請求碼和返回碼進行判斷
if(requestCode== REQUEST_CAL_WEIGHT && resultCode == RESULT_OK) {
}
】
【
概念:當新的Activity結束或返回上一個Activity時,需要返回一些結果,此時就需要設置并處理Activity的返回值。
1)startActivityForResult(Intentintent) // 開啟ActivityB
2)getIntent()// 在ActivityB中獲取來自ActivityA的Intent對象
3)setResult(intresultCode, Intent data) // 設置返回值(返回碼 + 數據)
4)finish() // 關閉ActivityB并將結果返回給ActivityA
5)onActivityResult(intrequstCode, int resultCode, Intent data) // 在ActivityA中處理來自ActivityB的返回值
請求碼和返回碼
請求碼:用于區分開啟的Activity
返回碼:用于標記結果返回的狀態
Activity.RESULT_CANCELED
Activity.RESULT_OK
Activity.RESULT_FIRST_USER
請求碼:用于區分開啟的Activity
返回碼:用于標記結果返回的狀態
Activity.RESULT_CANCELED
Activity.RESULT_OK
Activity.RESULT_FIRST_USER
】
【
publicvoidopenClick(View v) {
//開啟計算體重的界面
Intentintent =newIntent(this, CalWeightActivity.class);
//開啟一個Activity,開啟之后就沒有關聯了
// startActivity(intent);
//開啟一個Activity,并且獲取Activity的返回值
//參數:requestCode,請求碼,用于區分被開啟的Activity
startActivityForResult(intent,REQUEST_CAL_WEIGHT);
}
/**
* 當被開啟的Activity返回結果時調用
* 參數1:requestCode,請求碼
* 參數2:resultCode,返回碼(結果碼)
* 參數3:data,Intent對象,封裝了返回的數據
*/
protectedvoidonActivityResult(intrequestCode,intresultCode, Intent data) {
if(requestCode ==REQUEST_CAL_WEIGHT&& resultCode ==RESULT_OK) {
if(data !=null) {
doubleweight = data.getDoubleExtra("weight", -1);
tv_show.setText(weight +"");
}
}
}
/*
* 設置返回結果
* 注意:這個方法只是用于設置返回值,當調用完以后不會直接將結果返回,
* 而是要等到當前的Activity被關閉之后才會自動將結果返回
*
* 參數1:resultCode,返回碼,用于表示返回值的狀態
* 參數2:Intent,意圖對象,在這里的Intent只是用于Activity之間的數據傳遞,
* ????????????????????????????? 不是用于開啟某個組件,所以不需要包含任何組件的信息
*/
Intent intent =newIntent();
intent.putExtra("weight", weiht);
setResult(Activity.RESULT_OK,intent);
finish();//關閉當前的Acitivity,,將結果返回給
】
【
Activity生命周期的7個相關方法
onCreate(): 當Activity第一次被創建時被調用
onStart(): 當Activity可見時被調用
onResume(): 當Activity獲取焦點時被調用
onPause():當Activity失去焦點時被調用
onStop(): 當Activity不可見時被調用
onDestroy(): 當Activity被銷毀時被調用
onRestart(): 當Activity重新可見時被調用
各生命周期回調方法的使用場景
onCreate()、onDestroy——>? 界面退出之前的數據保存,如:短信草稿
onStart()、onStop()——>? 更新UI的操作,如:視頻播放、暫停,在Activity可見和不可見時調用
onResume()、onPause()——>? 取消界面上的焦點,如:暫停游戲,在Activity是在獲取和失去焦點時調用
onRestart(): 當Activity重新可見時被調用,從Activity不可見重新到可見時調用
Activity生命周期的三個狀態
Resumed: 運行狀態,位于前臺,可與用戶進行交互
Paused: 另一個Avtivity位于前臺,本Activity還可見,但是不可交互
Stoped: 另一個Activity位于前臺,完全遮擋本Activity
Activity的三種生命周期
完整生命周期:onCreate—> onStart —>onResume —> onPause —> onStop —> onDestroy
可視生命周期: onStart —> onResume —> onPause —> onStop
前臺生命周期: onResume —> onPause
思考題:
1、? 當前有一個Activity在前臺,當點擊返回()
返回:onPause():當Activity失去焦點時被調用------onStop():不可見--------onDestroy()銷毀
Home:onPause() :當Activity失去焦點時被調用------onStop():不可見
2、前臺ActivityA,開啟ActivityB?
A::onPause():當Activity失去焦點時被調用------onStop():不可見
B: onCreate —> onStart可見 —> onResume獲取焦點
==Android系統內部有一個內存管理機制,進程是分等級的,當高等級的進程需要使用內存又不夠用的時候,系統會自動殺死優先級較低的進程,將釋放出來的內存分配給高優先級的進程,當系統中內存又夠用的時候,系統會再自動將先前因內存不足被自動殺死的繼承重新開啟。
】
【Activity狀態保存
在某些情況下,系統可能會對Activity進行重構(重新構建)
。。。。。。。。。。。。。
在Activity重構的時候,會導致數據丟失,Android系統提供了狀態恢復機制用于保存Activity的狀態。
1、在onSaveInstanceState(BundleoutState)中保存數據
2、在onCreate(BundlesavedInstanceState)恢復數據
或者在onRestoreInstanceState(BundlesavedInstanceState)中恢復數據
如果在橫豎屏切換的時候不需要重構Activity,那么我們可以在清單文件中進行位置,配置方式如下:
android:configChanges="orientation|screenSize|keyboardHidden"
配置完屬性后,就可以放置在橫豎屏切換時重構Activity
ps:android:configChanges的作用就是 配置的屬性值如果發生改變就不會導致Activity的重構,取而代之的是會調用onConfigurationChanged()方法1、在onSaveInstanceState(BundleoutState)中對數據進行保存,將數據保存在outState對象中
2、從Bundle對象中讀取數據,讀取數據后重新更新到界面
a)在onCreate(BundlesavedInstanceState)方法中進行恢復
注意:需要判斷savedInstanceState是否為空
b)在onRestoreInstanceState(BundlesavedInstanceState)方法中進行恢復
注意:不需要判斷savedInstanceState是否為空
】
【
public class MainActivity extends Activity{
privateTextView tv_num;
privateint num = 0;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("mtag","onCreate");
tv_num= (TextView) findViewById(R.id.tv_num);
/*
* 恢復數據
* 這里要注意的是,當Activity第一次其中時,是不存在數據恢復的情況,
* 所以,Bundle的引用是null
*/
//?????????????? if(savedInstanceState!= null) {
//???????????????????????? intnum = savedInstanceState.getInt("num");
//???????????????????????? tv_num.setText(num+"");
//?????????????? }
}
//當配置發生改變時調用
@Override
publicvoid onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i("mtag","onConfigurationChanged");
if(newConfig.orientation== Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this,"橫屏", 0).show();
}else if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(this,"豎屏", 0).show();
}
}
/**
* 當Activity自動重構時調用,主要用于恢復Activity中的數據
*/
@Override
protectedvoid onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.i("mtag","onRestoreInstanceState");
intnum = savedInstanceState.getInt("num");
tv_num.setText(num+"");
}
/**
* 當Activity自動重構時調用,主要用于保存當前Activity的狀態(內部的數據)
* 參數:outState,Bundle對象,是框架傳入的一個對象,主要用戶保存Activity中的數據
*/
@Override
protectedvoid onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.i("mtag","onSaveInstanceState");
//將數據保存在Bundle對象中
outState.putInt("num",num);
}
@Override
protectedvoid onDestroy() {
super.onDestroy();
Log.i("mtag","onDestroy");
}
publicvoid add(View v) {
//每次點擊按鈕之后都會加1
tv_num.setText((++num)+"");
}
}】
1.8????任務和后退棧(Task and Back Stack)
【
概念
任務(Task)
一個應用程序一般都是由多個Activity組成的,task就是多個 Activity的集合
后退棧(Back Stack)
就是一個保存和管理應用程序中所有Activity的容器
用戶在進行操作時將與task中的Activity進行交互,這些Activity會按照啟動順序排隊存入后退棧
Android為什么要引入任務和后退棧的概念?
在Windows下可以同時開啟多個程序,并且可以在多個程序之間進行切換,在Andorid下也可以開啟多個程序,可以通過長摁home鍵來查看開啟的App,要實現在多個Activity之間進行切換,那么就要將已經打開的Activity保存在內存中,而Android系統是通過后退棧來存儲已經開啟的Activity,并記錄他們開啟的先后順序。
】
【android:launchMode=""在清單文件中配置即可
standard: 默認的啟動模式,每次啟動Activity都會創建一個新的Activity實例
singleTop:如果Activity位于棧頂,則不再生成實例,而是調用onNewIntent()方法
singleTask:如果存在實例,則帶至棧頂并銷毀它上面所有的Activity
singleInstance:無論當前Activity是否是同一個App的,都只用一個實例
】