Android flag詳解

一.Flag標誌位

在閱讀源碼的時候經常發現有一些標誌屬性使用一些位操作來判斷是否具有該標誌,增加標誌或者去除標誌。

如:

爲什麼要使用16進制呢?爲何不使用十進制0,1,2...?原因是因爲這樣就可以方便的用位運算來表示共同具有某些屬性或者直接判斷是否具有某個屬性。

上面這句話我們稍微來分析一下。拿文件的權限來分析一下,我們知道文件有三個權限:讀,寫,執行。分別用4 , 2 , 1來表示,這樣一來就可以很快速的知道文件所有的權限,比如5表示可讀可執行兩個權限,7表示可讀可寫可執行權限。

如果把上面的2進制換成10進制呢?結果就會變得很尷尬。假如上面三個權限分別用1 , 2 , 3表示,3這個就會很尷尬,因爲我們不知道這個值表示的是可讀可寫兩個權限還是僅僅一個執行權限。

Android源碼中主要針對FLAG的運算有三種

①. 增加屬性 "|"
如果需要向flag變量中增加某個FLAG,使用"|"運算符
    flag |= XXX_FLAG;
原因: 如果flag變量沒有XXX_FLAG,則 | 完後flag對應的位爲1,如果有XXX_FLAG,則 | 完後值不會變對應位還是1. 

②. 包含屬性 "&"
  如果需要判斷flag變量中是否包含XXX_FLAG,使用"&"運算符
  flag & XXX_FLAG  !=  0 或者 flag & XXX_FLAG = XXX_FLAG

原因: 如果flag變量裏包含XXX_FLAG,則&完後flag變量對應的位爲1,因爲XXX_FLAG的定義保證了只有一位非0,其他位都爲0,所以如果是包含的話&運算後值不爲0,值爲此XXX_FLAG的值,不包含的話值爲0. 

③.取消屬性 "&~"
  如果需要取消flag變量的XXX_FLAG, 使用 "&~". 
  flag &= ~XXX_FLAG;
原因: 先對XXX_FLAG進行取反 則XXX_FLAG原來非0的那一位變爲0,則使用&運算符後flag變量非0的那一位變爲0,則意味着flag變量不包含XXX_FLAG. 

這樣做的好處就是可以用一個值表示多種狀態。假如這裏有四種狀態:是否可點擊,是否獲取焦點。我們只需用flag標記 : 0x1,0x2,0x4,0x8 , 然後保存到一個值裏面就行,用以上的運算符就能快速的增加刪除以及判斷屬性了。

二.addFlags (int flags)和setFlags (int flags)區別

Public Intent addFlags (int flags)

增加額外的標誌到Intent(或者已經存在的flags值)

參數 flags 需要設置的新的flags

Returns(返回值)

返回相同Intent對象,用來將多個調用鏈接成一個調用的聲明

 

public Intent setFlags (int flags)

設置特定的flags去控制Intent如何執行。大部分的values 依賴於正在被執行的Intent組件的類型,特別是FLAG_ACTIVITY_* 這些flags全部用在Context.startActivity() 和

FLAG_RECEIVER_* 這些flags全部用在 Context.sendBroadcast().

具體內容詳情看task和back stack

參數 flags 設置要求的flags

Returns(返回值)

返回相同Intent對象,用來將多個調用鏈接成一個調用的聲明


 三.相關知識的理解

Task

Task就是一個任務棧,裏面用來存放Activity,第一個進去的(Activity)處於棧的最下面,而最後創建的(Activity)則處於棧的最上面。從Task中取出(Activity)是從最頂端取出,也就是說先進後出,後進先出。而Activity在Task中的順序是可以控制的,在Activity跳轉時用到Intent Flag可以設置新建Activity的創建方式。

Back Stack

字面意思,是回退棧的意思,它屬於數據結構中棧的一種。當從一個Activity 跳到另一個Activity的時候,如果不進行特殊的處理,就會有Activity被壓入棧。當回退棧爲空的時候,表示當前,已經到達了Lancher。因此,我們就可以知道BackStack就是一個存儲Activity的容器,一般情況下,每需要執行一個Task,都至少有一個回退棧,這個容器中也至少有一個Activity實例。

LanchMode的作用和使用方法

點擊以下文章:安卓啓動Launch mode

例子:

在已經啓動A,B,C,D四個Activity的情況下。再啓動C的時候,不希望是ABCDC,而是AB,而且B上的數據需要保留
    Intent it = new Intent(D.this,B.class);
    it.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//設置可以關掉它所跳到的界面之外已經開啓的activity在這裏是把C關閉
    it.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);//設置不要刷新即將跳轉的頁面
    D.this.startActivity(it);

四.各Flag(標誌)屬性 詳解

FLAG_GRANT_READ_URI_PERMISSION

如果設置了,Intent的接受者將被准許執行read操作(Intent 攜帶的URI數據和任何Clipdata中特定的URIs數據)的權限。

FLAG_GRANT_WRITE_URI_PERMISSION

如果設置了,Intent的接受者將被准許執行write操作(Intent 攜帶的URI數據和任何Clipdata中特定的URIs數據)的權限。

FLAG_GRANT_PERSISTABLE_URI_PERMISSION

當結合使用 flag_grant_read_uri_permission 和/或 flag_grant_write_uri_permission,URI權限授予可以堅持在設備重新啓動直到明確撤銷 用revokeuripermission(URI,int)。

FLAG_GRANT_PREFIX_URI_PERMISSION

當結合使用 flag_grant_read_uri_permission 和/或 flag_grant_write_uri_permission,URI權限授予適用於任何前綴匹配不同於原始的授予的URI。

FLAG_DEBUG_LOG_RESOLUTION

使能夠使用調試功能的flag。設置之後,日誌信息將在intent處理過程被輸出,爲了告訴你最後的解決列表被發現已創建。

FLAG_FROM_BACKGROUND

可以由調用者設置,以指示此意圖來自後臺操作,而不是來自直接用戶交互.。

FLAG_ACTIVITY_BROUGHT_TO_FRONT 

這個flag不能正常地被應用程序代碼設置,而是系統爲你設置由於在 launchMode 設置爲singleTask模式

FLAG_ACTIVITY_CLEAR_TASK

如果通過 Context.startactivity()去設置/啓動一個Intent,這個flag將導致任何存在的task,將與活動開始前清除的活動相關聯.

FLAG_ACTIVITY_CLEAR_TOP

如果已設置,並且正在啓動的活動已經在當前任務(backstack)中運行,那麼,而不是啓動該活動的新實例,而且它上面的所有其他活動都將被關閉,而這個意圖將作爲一個新的意圖傳遞到(現在的頂部)舊活動中.。

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

這個常數是在API級別21廢棄掉。在API 21執用 flag_activity_new_document 替代

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

如果設置,新活動不保存在最近啓動的活動列表中。

FLAG_ACTIVITY_FORWARD_RESULT

如果設置這個intent是被用來從一個現有的acitivity啓動到新的acitivity,現有activity的回覆目標將被轉移到新的activity。

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

這個flag不能正常地被應用程序代碼設置,而是系統爲你設置,如果這個活動正在展開的歷史堆棧(長按 Home鍵)。

FLAG_ACTIVITY_MULTIPLE_TASK

此標誌用來創建一個新的task和啓動一個活動到此任務

FLAG_ACTIVITY_NEW_DOCUMENT

此標誌用於將文檔打開到一個新的任務中,該任務源於intent啓動的活動。

FLAG_ACTIVITY_NEW_TASK

設置此標誌使activity將成爲此歷史堆棧上新任務的開始

1.如果D這個Activity在Manifest.xml中的聲明中添加了Task Affinity,系統首先會查找有沒有和D的Task Affinity相同的Task棧存在,如果有存在,將D壓入那個棧

2.如果D這個Activity在Manifest.xml中的Task Affinity默認沒有設置,則會把其壓入棧1,變成:A B C D,這樣就和標準模式效果是一樣的了。

FLAG_ACTIVITY_NO_ANIMATION

如果通過 Context.startactivity()去設置/啓動一個Intent,這個標誌將阻止系統執行一個活動去下一個活動的過渡動畫。

禁用掉系統默認的Activity切換動畫。

FLAG_ACTIVITY_NO_HISTORY

設置此標誌activity將不添加到回退棧(backStack)

FLAG_ACTIVITY_NO_USER_ACTION

設置此標誌,將阻止onuserleavehint()正常回調發生在當前最前的活動,在它被停下來作爲新啓動活動被帶到前面。

FLAG_ACTIVITY_PREVIOUS_IS_TOP

如果設置並使用此意圖從現有的一個activity a啓動到新activity b,新avitivity b將不會被視爲棧頂而是activity a,而是決定是否新意圖傳遞到頂部而不是啓動新的活動。

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

設置此標誌使這個活動要麼開始在一個新的任務或帶到現有的任務的頂部,那麼它將被啓動作爲任務的前門。

FLAG_ACTIVITY_REORDER_TO_FRONT

如果在通過 Context.startactivity()去設置/啓動一個Intent,如果需要啓動的activity已經運行,此標誌使被啓動的活動被帶到任務的歷史堆棧的前面.。

FLAG_ACTIVITY_SINGLE_TOP

如果設置,activity將不會被啓動如果其正在backstack的棧頂

FLAG_ACTIVITY_TASK_ON_HOME

如果在通過 Context.startactivity()去設置/啓動一個Intent,此flag將使新啓動任務置於當前活動任務的頂部(如果只有一個task時)。

FLAG_RECEIVER_REGISTERED_ONLY

如果設置,當發送一個廣播只有註冊接收器將被調用,沒有BroadcastReceiver組件將被啓動。

FLAG_RECEIVER_FOREGROUND

當發送廣播的時候設置了這個標誌,會允許接收者以前臺的優先級運行,有更短的時間間隔。正常廣播的接受者是後臺優先級,不會被自動提升。

FLAG_RECEIVER_REPLACE_PENDING

如果在發送廣播時設置了這個標誌,那新的廣播會替換掉那些已存在的相同廣播。相同的定義是通過Intent.filterEquals方法對兩個廣播的Intent處理返回true。 當匹配到相同的,新的廣播和對應的接收器會將待發送的廣播列表中已存在的替換掉,在列表中保留同樣的位置。這個標誌通常被粘性廣播(Sticky Broadcast)使用,只保證將最新的廣播的值傳遞給接收器。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章