1. 程式人生 > >Android——Activity簡介

Android——Activity簡介

本文是從個人學習過程中所記錄的筆記中經過再次整理而得,所有觀點僅代表個人理解,如有錯誤,還望指出。

  • 絕大部分Activity是用於和使用者互動的,Activity會建立一個互動視窗,可以通過呼叫setContentView(View)來放置一個佈局在activity的視窗中。
    通常是在PhoneWindow的DecorView中,顯示UI會延遲大概300ms左右,在此之前,View還沒有被填充,所以要在onCreate()中獲去View的尺寸,需要建立一個執行緒,線上程中等待300ms以上,再獲取View的尺寸。

  • Activity提供的視窗可以是充滿螢幕的,也可以是懸浮視窗(通過windowIsFloating來設定),或者嵌入到其它的Activity中,通過ActivityGroup來實現。

Activity生命週期圖

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中的狀態,不接受任何清理命令。