1、Activity初步認識:【建立、配置、啓動Activity】android
(一)、建立Activity:瀏覽器
建立Activity:繼承於Activity或其子類,重寫onCreate()方法。bash
(二)、Activity的註冊配置:app
做爲四大組件之一的Activity,必需要在AndroidManifest清單文件中進行註冊。若是沒有配置,而又在程序中啓動了該Activity,將拋出異常(ActivityNotFoundException)。ide
註冊配置的核心代碼:ui
<application
android:allowBackup=*"true"*
android:icon=*"@drawable/ic_launcher"*
android:label=*"@string/app_name"*
android:theme=*"@style/AppTheme"*>
<activity
android:name=*".MainActivity"*
android:label=*"@string/app_name"*>
<intent-filter>
<actionandroid:name=*"android.intent.action.MAIN"* />
<categoryandroid:name=*"android.intent.category.LAUNCHER"*/>
</intent-filter>
</activity>
<activity
android:name=*".HeadpicActivity"*
android:label=*"@string/title_activity_headpic"* >
</activity>
</application>
複製代碼
當在AndroidManifest清單文件中,設置多個頁面都是默認啓動頁,不會報錯,會由上向下以第一個配置的LAUNCHER 去運行!this
當在AndroidManifest清單文件中,若是不設置默認啓動頁,程序運行不了spa
(三)、啓動Activity:code
(四)、Activity之間交換數據:cdn
第一種方式:
第二種方式:【經常使用】
甲頁面利用bundle對象來保存全部須要傳遞的數值,經過intent的putExtras()方法傳值,乙頁面利用intent對象的getExtras()方法返回bundle對象,將全部接收的數據放在bundle對象中,利用bundle的get系列方法一一去除數據。
【備註:】若是甲頁面使用putExtras()方法傳值,則乙頁面使用getExtras()接收值。若是甲頁面使用putExtra()方法傳值bundle而且傳入bundle是有key值得,則乙頁面要使用getBundleExtra()方法接收值,拿到bundle
Activity之間是否能夠傳遞對象呢?【掌握Serializable的用法】
一、傳遞通常數據的核心代碼:
(1)、MainActivity頁面:
public void clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_tonext:
Intent intent = new Intent(MainActivity.this,NextActivity.class);
Bundle bundle = new Bundle();
bundle.putString("myname", "lgc");
bundle.putInt("age", 16);
intent.putExtras(bundle);
startActivity(intent);
break;
}
}
複製代碼
(2)、NextActivity頁面:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
// 接收第一個頁面的傳值
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String name = bundle.getString("myname");
int age = bundle.getInt("age");
this.setTitle(name + ":" + age);
}
複製代碼
2、Activity——調用另外一個Activity並返回結果:
(一)、概念:
甲頁面調用乙頁面,當用戶在乙頁面完成任務後,程序自動返回到甲頁面,而甲頁面必須可以獲取到用戶在完成乙頁面後傳遞的數據結果。
(二)、作法:
與普通的頁面交換數據不一樣的是,要使用startActivityForResult()方法來啓動另外一個Activity。
(三)、示例代碼:
一、MainActivity頁面:
public class MainActivity extend Activity {
private ImageView imageView_main_headpic;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView_main_headpic = (ImageView) findViewById(R.id.imageView_main_headpic);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true ;
}
public void clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_selectpic:
Intent intent = new Intent(MainActivity.this, HeadpicActivity.class);
startActivityForResult(intent, 0);
break;
}
}
@Override
protected void onActivityResult( int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0 && resultCode == 1) {
Bundle bundle = data.getExtras();
int imgid = bundle.getInt("imgId");
imageView_main_headpic.setImageResource(imgid);
}
}
}
複製代碼
二、NextActivity頁面:
public class HeadpicActivity extends Activity {
private GridView gridView_headpic_show;
// 定義數據源
private int [] imgIds = new int [] { R.drawable.img01, R.drawable.img02,
R.drawable.img03, R.drawable.img04, R.drawable.img05,
R.drawable.img06, R.drawable.img07, R.drawable.img08,
R.drawable.img09 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_headpic);
gridView_headpic_show = (GridView) findViewById(R.id.gridView_headpic_show);
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
for(int i = 0; i < imgIds.length; i++) {
Map<String, Object> map = **new** HashMap<String, Object>();
map.put("headpic", imgIds[i]);
map.put("picname", "頭像—" + i);
list.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.item_gridview_headpic, new String[] { "picname",
"headpic" }, new int[] {
R.id.text_item_gridview_picname,
R.id.imageView_item_gridview_headpic });
gridView_headpic_show.setAdapter(adapter);
gridView_headpic_show.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = getIntent();
Bundle bundle = new Bundle();
bundle.putInt("imgId", imgIds[position]);
intent.putExtras(bundle);
setResult(1, intent);
finish();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.headpic, menu);
return true;
}
複製代碼
3、Activity生命週期:
(一)、引入:人的生命週期是怎麼樣的?
(二)、Activity生命週期:
一、Activity一輩子中有七種不一樣的狀態。
【備註:】
A、七個生命週期組合:
B、七個生命週期按階段劃分:
二、定義生命週期的做用:
三、生命週期的金字塔圖
(三)、實例代碼操做:
04-23 03:51:29.750: I/MainActivity(741): ==MainActivity onCreate執行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onStart執行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onResume執行了
04-23 03:52:04.780: I/MainActivity(741): ==MainActivity onPause執行了
04-23 03:52:04.791: I/MainActivity(741): ==MainActivity onStop執行了
04-23 03:52:04.791: I/MainActivity(741): ==MainActivity onDestroy執行了
切換橫屏:
04-23 03:51:29.750: I/MainActivity(741): ==MainActivity onCreate執行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onStart執行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onResume執行了
04-23 03:52:04.780: I/MainActivity(741): ==MainActivity onPause執行了
04-23 03:52:04.791: I/MainActivity(741): ==MainActivity onStop執行了
04-23 03:52:04.791: I/MainActivity(741): ==MainActivity onDestroy執行了
04-23 03:51:29.750: I/MainActivity(741): ==MainActivity onCreate執行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onStart執行了
04-23 03:51:29.759: I/MainActivity(741): ==MainActivity onResume執行了
複製代碼
【橫豎屏切換時的生命週期問題的解決】
(一)、android:configChanges屬性
對android:configChanges屬性,通常認爲有如下幾點:
一、不設置Activity的android:configChanges時,切屏會從新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次
二、設置Activity的android:configChanges="orientation"時,切屏仍是會從新調用各個生命週期,切橫、豎屏時只會執行一次
三、設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會從新調用各個生命週期,只會執行onConfigurationChanged方法
可是,自從Android 3.2(API 13),在設置Activity的android:configChanges="orientation|keyboardHidden"後,仍是同樣 會從新調用各個生命週期的。由於screen size也開始跟着設備的橫豎切換而改變。因此,在AndroidManifest.xml裏設置的MiniSdkVersion和 TargetSdkVersion屬性大於等於13的狀況下,若是你想阻止程序在運行時從新加載Activity,除了設置"orientation", 你還必須設置"ScreenSize"。
解決方法: AndroidManifest.xml中設置android:configChanges="orientation|screenSize「
4、任務與回退棧:
(一)、任務Task:
一、概念:
一個任務(task)就是在執行某項工做時與用戶進行交互的Activity的集合。這些Activity按照被打開的順序依次被安排在一個堆棧中(回退棧)。
二、主屏頁面:
設備的主屏是大多數任務的啓動位置,當用戶觸摸一個應用程序啓動器圖標(或者app快捷圖標),應用程序的任務就會在前臺顯示。若是相關應用程序的任務不存在,那麼就會有一個新的任務被建立,而且應用程序打開的「主」Activity會做爲任務中的根Activity。
(二)、回退棧:
一、概念:
在當前的Activity啓動了另外一個Activity時,這個新的Activity被放到了堆棧的頂部,而且帶有焦點。前一個Activity並無消失,而是保存在回退棧中,此時它處於中止狀態。
當用戶按下回退按鈕時,當前的Activity會被從回退棧的頂部彈出(這個Activity被銷燬),而前一個Activity被恢復。堆棧中的Activity不會被從新排列。所以,回退棧的操做跟後進先出的對象結構是同樣的。
在用戶按下回退按鈕時,當前Activity被銷燬,而且前一個Activity被恢復。若是用戶繼續按回退按鈕,那麼回退棧中的每一個Activity會被依次彈出,前一個Activity會被顯示,直到用戶返回主屏(或者返回到任務開始時運行的那個Activity)。當全部的Activity從回退棧中被刪除時,這個任務就再也不存在了。
圖1:用一個時間表顯示了當前回退堆棧中的Activity之間在每一個時間點的處理過程
二、多個任務:
圖2. 兩個任務:任務B在前臺接受用戶交互,而任務A則在後臺等待被恢復。
【注意:】後臺中能夠同時擁有多個任務,可是若是用戶同時運行了不少後臺任務,系統爲了回收內存可能銷燬一些後臺的Activity,從而致使Activity的狀態丟失。
由於回退堆棧中的Activity未曾被從新排列,所以若是容許用戶從多個Activity中啓動一個特殊的Activity,那麼就會建立一個新的Activity實例,而且在堆棧的頂部彈出(而不是把以前的Activity實例帶到堆棧的頂端)。這樣在你的應用程序中一個Activity就可能被實例化屢次(甚至來自不一樣任務)。
複製代碼
(三)、Activity和Task的默認行爲的總結:
一、當Activity A啓動Activity B時,ActivityA被終止,可是系統保留了它的狀態(如滾動條的位置和錄入表單的文本)。若是用戶在Activity B中按回退按鈕,Activity A會使用被保存的狀態來進行恢復。
二、當用戶經過按主頁(Home)按鈕離開一個任務時,當前的Activity會被終止,而且被放入後臺。系統會保留任務中每一個Activity的狀態。若是用戶隨後經過選擇啓動圖標來恢復這個任務,那麼任務會來到前臺,而且恢復了堆棧頂部的Activity。
三、若是用戶按下回退按鈕,當前的Activity會從堆棧中被彈出而且被銷燬。堆棧中的前一個Activity會被恢復。Activity被銷燬時,系統不會保留Activity的狀態。
四、Activity可以被實例化屢次,甚至來自其餘任務。
5、Activity啓動模式:
在Android中每一個界面都是一個Activity,切換界面操做實際上是多個不一樣Activity之間的實例化操做。在Android中Activity的啓動模式決定了Activity的啓動運行方式。Android總Activity的啓動模式分爲四種:
複製代碼
(一)、Activity啓動模式設置:
<activity android:name=".MainActivity" android:launchMode="standard" />
複製代碼
(二)、Activity的四種啓動模式:
1. standard(備註:standard是系統默認的啓動模式。)
標準啓動模式,每次激活Activity時都會建立Activity,並放入任務棧中。每一個窗體的getTaskId()保持不變,可是this.hashCode()發生改變。
2. singleTop
若是在任務的棧頂正好存在該Activity的實例, 就重用該實例,而不會建立新的Activity對象,不過它會調用onNewIntent()方法。若是棧頂部不存在就會建立新的實例並放入棧頂(即便棧中已經存在該Activity實例,只要不在棧頂,都會建立實例)。會回調onNewIntent()方法。
3. singleTask
若是在棧中已經有該Activity的實例,就重用該實例(會調用實例的onNewIntent())。重用時,會讓該實例回到棧頂,所以在它上面的實例將會被移除棧。若是棧中不存在該實例,將會建立新的實例放入棧中。
和singleTop在名字上便可看出區別,即singleTop每次只檢測當前棧頂的Activity是不是咱們須要請求建立的,而singleTask則會檢測棧中所有的Activity對象,從上向下,若是檢測到是咱們所請求的則會消滅此Activity對象上面的對象,直接把檢測到的咱們須要的Activity置爲棧頂。
4. singleInstance
與singleTask模式的區別是存放singleInstance模式窗口對象的回退棧不能有其餘任何窗口對象。所以若是該窗口不存在,則要新建任務來存放該singleInstance模式窗口。也就是說getTaskId()會發現任務id發生了變化。
此啓動模式和咱們使用的瀏覽器工做原理相似,在多個程序中訪問瀏覽器時,若是當前瀏覽器沒有打開,則打開瀏覽器,不然會在當前打開的瀏覽器中訪問。此模式會節省大量的系統資源,由於他能保證要請求的Activity對象在當前的棧中只存在一個。
複製代碼
總之,在開發Android項目時,巧妙設置Activity的啓動模式會節省系統開銷和提升程序運行效率。
【備註:】
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation|screenSize"
一、不設置Activity的android:configChanges時,切屏會從新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次
二、設置Activity的android:configChanges="orientation"時,切屏仍是會從新調用各個生命週期,切橫、豎屏時只會執行一次
三、設置Activity的android:configChanges="keyboardHidden"時,切屏仍是會從新調用各個生命週期,切橫、豎屏時只會執行一次
四、設置Activity的android:configChanges="orientation|screenSize|keyboardHidden"時,切屏不會從新調用各個生命週期,只會執行onConfigurationChanged方法