Android——Activity簡介
本文是從個人學習過程中所記錄的筆記中經過再次整理而得,所有觀點僅代表個人理解,如有錯誤,還望指出。
絕大部分Activity是用於和使用者互動的,Activity會建立一個互動視窗,可以通過呼叫setContentView(View)來放置一個佈局在activity的視窗中。
通常是在PhoneWindow的DecorView中,顯示UI會延遲大概300ms左右,在此之前,View還沒有被填充,所以要在onCreate()中獲去View的尺寸,需要建立一個執行緒,線上程中等待300ms以上,再獲取View的尺寸。Activity提供的視窗可以是充滿螢幕的,也可以是懸浮視窗(通過windowIsFloating來設定),或者嵌入到其它的Activity中,通過ActivityGroup來實現。
Activity生命週期圖
當一個activity被啟動時,他就會處於Activity Task的頂端。
大部分實現Activity的子類需要重寫onCreate(Bundle)和onPause(),在onPause()方法中通常使用ContentProvider來儲存使用者資訊的改變,或者使用SharedPreference來儲存使用者設定的改變。在這個方法中通常也清除Activity產生的資源,避免造成浪費。
當一個activity失去焦點,但是任然可見時,它就會進入暫停狀態onPause(),此時它會保留所有的狀態和成員資訊;但此時的activity將可能會被系統關閉。
activity通常會頻繁的呼叫onPause()和onResume()方法,所以這兩個方法中執行的程式碼應該是較為輕量的。但任然應該把儲存資料的程式碼寫在onPause()方法當中。當呼叫onPause()時,會呼叫onSaveInstaneState(Bundle)和onRestoreInstanceState()來暫存view的狀態,並且將在呼叫onCreate(Bundle)時接收,但這個方法並不屬於activity生命週期的一部分,所以有些時候它並不會被呼叫,如果複寫這兩個方法將能擴充套件它的功能,並且使activity更加健壯,以應對一些不可預見的錯誤。
對於需要重複載入的事務,應該寫在onResume()中。onCreate()中就放一些初始化的操作,即這些操作只需要執行一次。
通過設定view的android:saveEnable屬性或者呼叫setSaveEnable()可以決定view的狀態state是否被儲存。
當一個activity失去焦點,並且不可見時,它就會進入停止狀態onStop(),此時它任然能保留狀態和成員資訊;但此時的activity更容易被系統關閉。呼叫onRestart()方法可以重新啟動activity。
對於啟動了另一個activity的情況,只有當被啟動的activity執行到onResume()時,才能知道它是否會使當前的activity變得不可見,此時才能決定當前的activity是否呼叫onStop()。
兩個Activity切換執行時的生命週期
假設有A,B兩個Activity,
B完全覆蓋A的情況:
當B完全呈現時,即B執行了onResume(),那麼A就會執行onStop();在此之前,A是處於 onPuase()狀態。
B沒有完全覆蓋A的情況:
當一個B完全呈現時,即B執行了onResume(),A任然出於onPuase()狀態。
Activity將在呼叫onDestroy()時釋放掉所有的資源;在這個方法中呼叫isFinishing()方法來判斷是否activity執行完成,否則就不要執行銷燬。
當系統配置改變時(比如語言、螢幕方向等),現行的activity將被呼叫onDestory()方法,然後自動呼叫onCreate()重新建立Activity;
如果不希望這些發生,可以在Manifest.xml中新增android:configChanges屬性,新增這個屬性之後,當配置發生改變時將直接呼叫onConfigrationChanged()方法,而不會呼叫onCreate()。
Activity的兩種啟動方式
通過startActivity(Intent)啟動。
通過startActivityForResult(Intent)啟動;需要重寫onActivityResult(int requastCode,int resultCode,Intent data)方法,並在該方法中處理返回的資料;並且在被啟動activity中需要呼叫setResult(int resultCode,Intent intent)方法來設定結果。
通過
startActivity(intent,ActivityOptions.makeScreenTransitionAnimation(this).toBundle())
來啟動,可以使被啟動的Activity有動畫效果。後面的文章會進一步講解。
儲存Activity中資料的兩種方式
通過資料庫Database儲存。
通過SharedPreferences.note 儲存。
例子:
public class CalendarActivity extends Activity {
//...
static final int DAY_VIEW_MODE =0;
static final int WEEK_VIEW_MODE =1;
private SharedPreferences mPrefs;
private int mCurViewMode;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
/**
* 該方法用於獲得應用程式中的SharedPreferences物件。沒有則會建立。
* @param1 :SharedPreferences的檔名。
* @param2 :開啟模式。這裡MODE_PRIVATE為私有模式,只能在該類中使 用。
*/
SharedPreferences mPrefs = getSharedPreferences("test",MODE_PRIVATE);
/**
* 該方法是獲得SharedPreferences中對應標籤的值。
*/
mCurViewMode = mPrefs.getInt("view_mode", DAY_VIEW_MODE);
}
protected void onPause(){
super.onPause();
/**
* 使用edit()方法獲得SharedPreferences的SharedPreferences.Editor屬性。
*/
SharedPreferences.Editor ed = mPrefs.edit();
/**
* 使用該方法以鍵值對方式儲存資料在SharedPreferences中。
*/
ed.putInt("view_mode", mCurViewMode);
/**
* 記得呼叫commit()提交
*/
ed.commit();
}
}
常用方法
方法 | 作用 |
---|---|
onCreateContextMenu(ContextMenu menu,View v,ContextMenu.ContextMenuInfo menuInfo) | 每次context menu被顯示時都會被呼叫 |
registerForContextMenu(View) | 註冊一個View到context view中,需要設定一個監聽器監聽它 |
onCreateContextMenuListener | |
unregisterForContextMenu(View) | 移除context menu中的view的監聽器 |
openContextMenu(View) | 開啟context menu |
onContextItmeSelected(MenuItemitem) | 通過重寫這個方法可以實現對MenuItem的控制 |
onContextMenuClosed(Menu menu) | 通過重寫這個方法可以實現當menu被關閉時的控制 |
closeContextMenu() | 使用程式碼關閉環境選單 |
onCreateOptionsMenu(Menu menu) | 建立一個optionsMenu,這個方法只會被呼叫一次 |
openOptionsMenu() | 開啟option menu |
onOptionsItemSelected(MenuItem) | 通過重寫這個方法來控制item被選擇時的活動 |
closeOptionsMenu() | 使用程式碼關閉選項選單 |
onOptionsMenuClosed(Menu menu) | 通過重寫這個方法來控制option menu被關閉時的活動 |
onCreatePanelMenu(int featureId,Menu menu) | 建立一個menu,並指定它的id |
onMenuOpened(int featureId,Menu menu) | 通過重寫這個方法來控制menu被開啟時的活動 |
onMenuItemSelected(int featureld,MenuItem item) | 處理item被選擇的事件,通過feature來分辨這些item是哪一個panel中的 |
onPanelClosed(int featureId,Menu manu) | 通過重寫這個方法來控制menu被關閉時的活動 |
onCreateView(View parent,String name,Context context,AttributeSet attrs) | 建立一個View物件 parent:指定這個view建立在那個View中,可以為空。 name:名稱。 context:當前的context物件。 attrs:xml中指定的填充屬性 |
onCreateView(String name,Context,AttributeSet attrs) | 建立一個View物件 |
onDetachedFromWindow() | 和window解除繫結關係 |
createPendingResult(int requestCode,Intent data,int flags) | 建立一個PendingIntent物件,其它activity可以通過它來發送result到本activity的onActivityResult(int,int,Intent)中 |
dispatchGenericMotionEvent(MotionEvent ev) | 處理一般的移動事件,通過重寫來自定義處理。什麼時候觸發? |
dispatchKeyEvent(KeyEvent event) | 處理鍵盤事件,通過重寫來自定義處理 |
onKeyDown(int keyCode,KeyEvent event) | 處理按鍵按下事件 |
onKeyUp(int keyCode,KeyEvet event) | 處理按鍵彈起事件 |
onKeyLongPressed(int keyCode,KeyEvent event) | 處理按鍵長按事件 |
onKeyMultiple(int keyCode,int repeatCount,KeyEvent event) | 處理按鍵多次點選事件 |
onLowMemory() | 處理低記憶體事件 |
dispatchTouchEvent(MotionEvent ev) | 處理觸控式螢幕幕的事件,通過重寫來自定義處理 |
onTouchEvent(MotionEvent event) | 處理螢幕觸控事件 |
dispatchTrackballEvent(MotionEvent ev) | 處理軌跡事件,通過重寫來自定義處理。什麼時候觸發? |
findViewById(int id) | 返回一個View |
finish() | 呼叫這個方法之後自動呼叫onDestroy() |
getActionbar() | 獲得Activity的ActionBar |
getApplication() | 獲得Activity所屬的Application |
getCallingActivity() | 獲得啟動這個Activity的Activity |
getCallingPackage() | 獲得啟動這個Activity的Activity的包名 |
getIntent() | 獲得啟動這個activity的Intent |
getComponentName() | 獲得本Activity的名稱 |
getLocalClassName() | 獲得去掉包名的本activity類名 |
getWindow() | 獲得當前activity的視窗 |
getWindowManager() | 獲得視窗管理器WindowManager |
getContentScene() | 獲得呈現當前視窗的內容的Scene |
getContentTransitionManafer() | 獲得視窗的預設過度管理器 |
getCurrentFocus() | 獲得當前視窗中被聚焦的view |
getFragmentManager() | 獲得與activity相關的fragments的FragmentManager |
getLayoutInflater() | 獲得佈局填充器LayoutInflater |
getLoaderManager() | 獲得LoaderManager,沒有的檢索到會建立一個 |
getMediaControler() | 獲得MediaControler,這是終態的 |
getMenuInflater() | 獲得當前context中的選單填充器MenuInflater |
getPreferences(int mode) | 獲得一個SharedPreferences物件,它的名稱使用的是activity的類名,在它的底層呼叫的是getSharedPreferences(String,int) |
getReferrer() | 獲得一個Uri物件, |
getTaskId() | 獲得activity所線上程的id |
isChlid() | 判斷activity是否套嵌在其他activity中 |
isFinish() | 判斷當前activtiy是否完成 |
isVoiceInteraction() | 判斷這個activity是否是Voice互動的一個部分 |
getVoiceInteraction() | 獲得VoiceInteraction,如果這個activity是voiceInteraction的一個部分 |
onActionModeFinished(ActionMode mode) | 通知activity一個動作完成了 |
onActionModeStart(ActionMode mode) | 通知activity一個動作開始了 |
onAttachFragment(Fragment fragment) | 在呼叫了Fragment.onAttach()之後和Fragment.onCreate()之前會被自動呼叫requestPermissions(String[] permission,int requestCode)請求許可權 |
setActionBar(Toolbar toolbar) | 設定一個toolbar代替antionbar |
setContentView(View) | |
setContentView(int layoutResID) | |
makeSceneTransitionAnimation(Activity,View sharedElement,String sharedElementName) | |
setProgress(int progress) | 設定一個進度條在title上,必須先呼叫requestWindowFeature(int),progress:範圍為10000 |
setProgressBarVisibility(bolean visible) | 設定進度條的可見性 |
setSecondaryProgress(int secondaryProgress) | 設定第二條進度條在title上 |
setProgressBarIndeterminate(boolean indeterminate) | 設定title上的水平進度條是否應該被模糊 |
setProgressBarIndeterminateVisibility(boolean visible) | 設定indeterminate progress的可見性 |
requestWindowFeature(int featureId) | 能夠擴充套件視窗特性 |
setResult(int resultCode,Intent data) | |
setTitle() | |
setVisible(boolean visible) | 設定activity視窗的可見性 |
startLockTask() | 開始鎖定activity |
showLockTaskEscapeManage() | 在鎖定acivity期間顯示訊息 |
stopLockTask() | 停止鎖定activity |
onSearchRequested(SearchEvent searchEvent) | 當啟動搜尋時會呼叫這個方法,重寫這個方法來自定義搜尋 |
Activity的屬性
name:和java程式相同。
label:活動的標題。
launchMode:啟動模式。
Launch Mode | 是否存在多個例項 | Comments |
---|---|---|
“standard” | Yes | 預設值。系統總是建立一個新的activity例項。因此,任務棧中會存在多個相同的activity例項。 |
“singleTop” | 看條件。 | 如果任務棧頂存在一個該activity的例項,則不會重新建立activity例項,而是將intent傳送給這個例項,並跳轉到這個activity。否則會建立新的activity例項。 |
“singleTask” | No | 如果任務棧中存在一個該activity例項,就不會建立新的activity例項。而是將intent傳送給已存在的activity例項,並且通過移除它前面的所有Activity來將它置於棧頂。 |
“singleInstance” | No | 和singleTask相同,但是一個任務棧中只存在一個activity例項。比如a啟動b(singleInstance),b啟動c,當從c按返回鍵時,將直接跳轉回a,而不是b。因為b是在一個單獨的任務棧中。 |
使用Intent的flag屬性來設定Activity啟動模式
Intent.FLAG_ACTIVITY_CLEAR_TOP
和singleTask一樣。Intent.FLAG_ACTIVITY_SINGLE_TOP
和singleTop一樣。Intent.FLAG_ACTIVITY_NEW_TASK
在一個新的task中啟動activity。類似single instance,但這每一次都會建立新的例項。Intent.FLAG_ACITVITY_NO_HISTORY
當離開該activity時,它就會被移除。使用finishAndRemoveTask()去完成所有的activity並移除task。
清除Activity Task
在Manifest中設定<activity>
的以下屬性:
- clearTaskOnLaunch
每次啟動該acitvity時,都清除其它的activity。 - finishOnTaskLaunch
當再次返回該activity時,它會被finish()掉。 - alwaysRemaindTaskState
總是保留該activity在task中的狀態,不接受任何清理命令。