一、萬事開頭的序 網上看見大牛們的博客寫的那樣精彩,各種羡慕之情溢於言表。幾次衝動均想效仿牛人寫些博客來記錄下自己的心得體會,但均無感亦或是感覺容易被噴,相信很多菜鳥和我一樣都有過這樣的擔憂。萬事開頭難,不逼一下自己怎麼知道自己能不能飛起來。由於本人處於初學階段,寫此博客僅是對前輩總結的review ...
一、萬事開頭的序
網上看見大牛們的博客寫的那樣精彩,各種羡慕之情溢於言表。幾次衝動均想效仿牛人寫些博客來記錄下自己的心得體會,但均無感亦或是感覺容易被噴,相信很多菜鳥和我一樣都有過這樣的擔憂。萬事開頭難,不逼一下自己怎麼知道自己能不能飛起來。由於本人處於初學階段,寫此博客僅是對前輩總結的review,對自己記憶的加深及後續使用的方便查找。請各位看官將就看看,手下留情。在此謝過!有錯的地方或者更好的心得體會歡迎隨時騷擾!
二、Activity介紹
Android中常說的四大組件包括:Activity、Service、Broadcast、Content Provider
其中最基礎也是最常見的就是今天review的主題:Activity
Activity存在的意義:用戶與Android系統的交互的途徑
三、Activity的生命周期
老套路先上經典的生命周期圖:
(1)正常情況下的生命周期
Activity的生命周期主要由上述8個方法組成
- onCreate表示Activity已經被創建(初始化)
在該方法中我們可以做一些初始化的相關操作
- 載入佈局資源文件:setContentView(R.layout.XX);
- 初始化數據:findViewById(R.id.XX);
- onRestart 通常在Activity從不可見, 重新變為可見時, 在onStart之前調用
- onStart 表示Activity已經顯示出來, 但是不能進行交互
- onResume 表示Activity不僅僅顯示出來, 而且已經在前臺活動
- onPause 表示Activity退出前臺活動
在該方法中可以做以下操作:
1: 儲存數據
2: 停止動畫
onStop:表示Acitivity正在停止或者即將被銷毀
onDestroy:表示Activity的銷毀, 所做的操作和onCreate正好相反
PS: 耗時操作不要放到onPause或onStop中
- 首次打開:onCreate()->onStart()->onResume()
- 按back鍵結速應用程式:onPause()->onStop()->onDestory()
- 按home鍵隱藏應用程式:onPause()->onStop()//此時程式未銷毀
- 再次啟動應用程式:onRestart()->onStart()->onResume()
- 從Activity(A)跳轉到Activity(B):onPause(A)->onCreate(B)->onStart(B)->onResume(B)->onStop(A)
(2)異常情況下的生命周期
當用戶轉動屏幕時,Activity銷毀並重建的過程如下:
onPause()->onSaveInstanceState()->onStop()->onDestory()->onCreate()->onStart()->onRestoreInstanceState()->onResume()
系統自帶的控制項, 如TextView的文本內容Android系統會幫我們保存和恢復
App的狀態, 則需要我們自己在onSaveInstanceState和onRestoreInstanceState中保存和恢復
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Log.i(TAG, "onSaveInstanceState"); outState.putString(BUNDLE_DATA, "xyz"); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); Log.i(TAG, "onRestoreInstanceState: " + savedInstanceState.getString(BUNDLE_DATA)); }View Code
我們能否在系統配置更新時, 自己對Activity的生命周期進行控制呢?
答案是可以的, android提供了這樣的機制
我們在AndroidManifest.xml中的Activity描述中添加如下配置
android:configChanges="orientation|screenSize"
再次旋轉屏幕看看, Activity並沒有銷毀和重建了
四、Activity啟動模式
與Activity生命周期息息相關的是Activity啟動模式,不同的啟動模式,導致的Activity生命周期則不同。
Activity有如下4種啟動模式:
- standard
- singleTop
- singleTask
- singleInstance
1: standard
Step 1: (standard launch)FirstActivity
Current Task Stack:
++++FirstActivity
Step 2: (standard launch)SecondActivity
Current Task Stack:
++++SecondActivity
++++FirstActivity
Step 3: (standard launch)FirstActivity
Current Task Stack:
++++FirstActivity
++++SecondActivity
++++FirstActivity
standard下: 總是會新建一個Activity入棧
Standard,預設的啟動模式,只要激活了Activity,就會創建一個新的實例,並放入任務棧中,這樣任務棧中可能同時存在一個Activity的多個實例。
2: singleTop
Step 1: (standard launch)FirstActivity
Current Task Stack:
++++FirstActivity
Step 2: (standard launch)SecondActivity
Current Task Stack:
++++SecondActivity
++++FirstActivity
Step 3: (singleTop launch)SecondActivity
Current Task Stack:
++++SecondActivity
++++FirstActivity
singleTop下: 如果棧頂是該Activity, 則不新建, 如果棧頂不是該Activity, 則新建該Activity
SingleTop,激活Activity時,如果棧頂是Activity,就不會創建新的實例,如果棧頂不是這個Activity,則會創建新的實例對象。
3: singleTask
Step 1: (standard launch)FirstActivity
Current Task Stack:
++++FirstActivity
Step 2: (standard launch)SecondActivity
Current Task Stack:
++++SecondActivity
++++FirstActivity
Step 3: (singleTask launch)FirstActivity
Current Task Stack:
++++FirstActivity
singleTask下: 如果棧里已經存在該Activity, 即pop到該Activity, 如果棧里沒有該Activity, 則新建Activity
singleTask,如果棧中存在Activity的實例,則將棧中該實例以上的其他Activity的實例移除,讓該Activity的實例處於棧頂,如果棧中不存在該實例,則創建新的實例。
4: singleInstance
Step 1: (standard launch)FirstActivity
Current Task Stack:
++++FirstActivity
Step 2: (singleInstance launch)ThirdActivity
Current Task Stack:
++++FirstActivity ++++ThirdActivity
Step 3: (standard launch)SecondActivity
Current Task Stack:
++++SecondActivity
++++FirstActivity ++++ThirdActivity
singleInstance下: 會新開一個棧, 單獨放置該Activity
多個應用共用Activity的一個實例,不論是否是同一個應用,只要是激活該Activity,都重用這個實例。
五、Activity實例
1.Activity註冊
1 // in AndroidManifest.xml 2 <activity android:name=".SecondActivity" > 3 </activity>View Code
2.Activity之Intent
1 // in FirstActivity.java 2 @Override 3 protected void onCreate(Bundle savedInstanceState) { 4 super.onCreate(savedInstanceState); 5 setContentView(R.layout.activity_first); 6 Button standardButton = (Button) findViewById(R.id.standard_button); 7 standardButton.setOnClickListener(new OnClickListener() { 8 @Override 9 public void onClick(View arg0) { 10 Intent intent = new Intent(FirstActivity.this, 11 SecondActivity.class); 12 startActivity(intent); 13 } 14 }); 15 }View Code
3.Activity之Intent-Filter
1 //in mainifest.xml 2 <intent-filter> 3 <action android-name="android.intent.action.MAIN" /> 4 <category android-name="android.intent.category.LAUNCHER" /> 5 </intent-filter>View Code
4.Activity間通信: FirstActivity -> SecondActivity
1 // in FirstActivity.java 2 public static final String EXTRA_DATA = "extra_data"; 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_first); 7 Button standardButton = (Button) findViewById(R.id.standard_button); 8 standardButton.setOnClickListener(new OnClickListener() { 9 @Override 10 public void onClick(View arg0) { 11 Intent intent = new Intent(FirstActivity.this, 12 SecondActivity.class); 13 intent.putExtra(EXTRA_DATA, "cba"); 14 startActivityForResult(intent, REQUEST_CODE); 15 } 16 }); 17 } 18 // in SecondActivity.java 19 @Override 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_second); 23 Intent intent = getIntent(); 24 Toast.makeText( 25 SecondActivity.this, 26 "Data from FirstActivity: " 27 + intent.getStringExtra(FirstActivity.EXTRA_DATA), 28 Toast.LENGTH_LONG).show(); 29 }View Code
5.Activity間通信: SecondActivity -> FirstActivity
1 // in FirstActivity.java 2 protected void onCreate(Bundle savedInstanceState) { 3 super.onCreate(savedInstanceState); 4 setContentView(R.layout.activity_first); 5 Button standardButton = (Button) findViewById(R.id.standard_button); 6 standardButton.setOnClickListener(new OnClickListener() { 7 @Override 8 public void onClick(View arg0) { 9 Intent intent = new Intent(FirstActivity.this, 10 SecondActivity.class); 11 startActivityForResult(intent, REQUEST_CODE); 12 } 13 }); 14 } 15 // in SecondActivity.java 16 @Override 17 protected void onResume() { 18 super.onResume(); 19 Intent intent = new Intent(); 20 intent.putExtra(EXTRA_DATA, "abc"); 21 setResult(Activity.RESULT_OK, intent); 22 } 23 // in FirstActivity.java 24 @Override 25 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 26 if (resultCode != Activity.RESULT_OK) { 27 return; 28 } 29 switch (requestCode) { 30 case REQUEST_CODE: 31 Toast.makeText( 32 FirstActivity.this, 33 "Result from SecondActivity: " 34 + data.getStringExtra(SecondActivity.EXTRA_DATA), 35 Toast.LENGTH_LONG).show(); 36 break; 37 default: 38 break; 39 } 40 }View Code
6.配置Activity啟動模式
靜態方式
即在AndroidManifest.xml中配置
android:launchMode="singleTop"
android:launchMode="singleTask"
android:launchMode="singleInstance"
動態方式
即在源碼中配置
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);