真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

android進(jìn)程,android 系統(tǒng)進(jìn)程

android進(jìn)程管理機(jī)制

Android系統(tǒng)與其他操作系統(tǒng)有個(gè)很不一樣的地方,就是其他操作系統(tǒng)盡可能移除不再活動(dòng)的進(jìn)程,從而盡可能保證多的內(nèi)存空間,而Android系統(tǒng)卻是反其道而行之,盡可能保留進(jìn)程。Android這樣設(shè)計(jì)有什么優(yōu)勢(shì)呢?又是通過(guò)怎樣的方法來(lái)管理這些被保留的進(jìn)程的呢?Android用戶又該如何正確使用手機(jī)從而更好發(fā)揮Android系統(tǒng)所特有的優(yōu)勢(shì)呢?本文將一一為您解開(kāi)這些謎團(tuán)。

成都創(chuàng)新互聯(lián)公司是專業(yè)的東寧網(wǎng)站建設(shè)公司,東寧接單;提供成都做網(wǎng)站、網(wǎng)站設(shè)計(jì),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行東寧網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!

? 本文的主要內(nèi)容如下:

一、Android進(jìn)程管理的特殊設(shè)計(jì)

? ?Linux系統(tǒng)對(duì)進(jìn)程的管理方式是一旦進(jìn)程活動(dòng)停止,系統(tǒng)就會(huì)結(jié)束該進(jìn)程。盡管Android基于Linux Kernel,但在進(jìn)程管理上,卻采取了另外一種獨(dú)特的設(shè)計(jì):當(dāng)進(jìn)程活動(dòng)停止時(shí),系統(tǒng)并不會(huì)立刻結(jié)束它,而是會(huì)盡可能地將該進(jìn)程保存在內(nèi)存中,在以后的某個(gè)時(shí)間,一旦需要該進(jìn)程,系統(tǒng)就會(huì)立即打開(kāi)它,而不用再做一些初始化操作。只有當(dāng)剩余內(nèi)存不夠用了,為了維持新開(kāi)啟的進(jìn)程或者比較重要的進(jìn)程的正常運(yùn)行,系統(tǒng)才會(huì)選擇性地殺掉一些不重要的內(nèi)存,騰出內(nèi)存空間來(lái),所以Android系統(tǒng)永遠(yuǎn)不會(huì)有內(nèi)存不足的提示。

二、Android獨(dú)特進(jìn)程管理設(shè)計(jì)的好處

? Android這種獨(dú)特的設(shè)計(jì),也正是Android標(biāo)榜的優(yōu)勢(shì)之一,這有兩個(gè)好處:

1、最大限度地提高內(nèi)存的使用率。

? ?比如,你的內(nèi)存是8G,如果每次使用完某個(gè)進(jìn)程就殺掉,那么被使用的內(nèi)存基本上會(huì)始終保持在某個(gè)值,比如4G以內(nèi),那么內(nèi)存的使用率就總是保存在50%以內(nèi),剩余的4G內(nèi)存形同虛設(shè),發(fā)揮用處的機(jī)會(huì)非常少。而Android的這種設(shè)計(jì),就可以做到有多少內(nèi)存就用多少內(nèi)存,盡可能大地提高內(nèi)存使用率。同樣比如有8G內(nèi)存,使用完的進(jìn)程仍保留在內(nèi)存中,累積下來(lái),被使用的內(nèi)存就盡可能地會(huì)接近8G。

2、提高再次啟動(dòng)時(shí)的啟動(dòng)速度

? ?被駐留在內(nèi)存中不再活動(dòng)的進(jìn)程(后臺(tái)進(jìn)程或空進(jìn)程,后面會(huì)再講到),很多是經(jīng)常需要使用的,當(dāng)再次使用該進(jìn)程的時(shí)候,系統(tǒng)立即打開(kāi)它,而不需要再重新初始化。例如,我們常用的瀏覽器,當(dāng)暫時(shí)不再使用時(shí),按下Home鍵或Back鍵,瀏覽器進(jìn)程就變成了不再活動(dòng)的進(jìn)程。如果下次又要使用了,點(diǎn)擊多任務(wù)鍵,在最近使用應(yīng)用列表中點(diǎn)擊瀏覽器即可,瀏覽器界面仍然保持著退出前的界面。但如果退出時(shí)把該進(jìn)程移除了,那么再次使用時(shí),就需要重新初始化,然后進(jìn)入該應(yīng)用,這往往會(huì)花費(fèi)不少的時(shí)間。

三、Android進(jìn)程的五個(gè)等級(jí)

? ? Android系統(tǒng)將盡量長(zhǎng)時(shí)間地保持應(yīng)用進(jìn)程,但為了新建進(jìn)程或運(yùn)行更重要的進(jìn)程,最終需要移除舊進(jìn)程來(lái)回收內(nèi)存。為了確定保留或終止哪些進(jìn)程,系統(tǒng)會(huì)根據(jù)進(jìn)程中正在運(yùn)行的組件以及這些組件的狀態(tài),將每個(gè)進(jìn)程放入“重要性層次結(jié)構(gòu)”中。必要時(shí),系統(tǒng)會(huì)首先消除重要性最低的進(jìn)程,然后是重要性略遜的進(jìn)程,以此類推,以回收系統(tǒng)資源。該“重要性層級(jí)結(jié)構(gòu)”將進(jìn)程分為了五個(gè)等級(jí):

1、前臺(tái)進(jìn)程(foreground)

? ?前臺(tái)進(jìn)程是指那些有組件正和用戶進(jìn)行交互的應(yīng)用程序的進(jìn)程,也稱為Active進(jìn)程。這些都是Android嘗試通過(guò)回收其他應(yīng)用程序來(lái)使其保持相應(yīng)的進(jìn)程。這些進(jìn)程的數(shù)量非常少,只有等到最后關(guān)頭才會(huì)終止這些進(jìn)程,是用戶最不希望終止的進(jìn)程。例如:而當(dāng)你運(yùn)行瀏覽器這類應(yīng)用時(shí),它們的界面就會(huì)顯示在前臺(tái),它們就屬于前臺(tái)進(jìn)程,當(dāng)你按home鍵回到主界面,他們就變成了后臺(tái)程序。

? ?如果一個(gè)進(jìn)程滿足以下任一條件,即視為前臺(tái)進(jìn)程:

?(1)托管處于活動(dòng)狀態(tài)的Activity,也就是說(shuō),它們位于前臺(tái)并對(duì)用戶事件進(jìn)行響應(yīng),此時(shí)的情形為響應(yīng)了Activity中的onResume()生命周期方法,但沒(méi)有響應(yīng)onPause()。

?(2)托管正在執(zhí)行onReceive()方法處理事件程序的BroadcastReceiver。

?(3)托管正在執(zhí)行onStart()、onCreate()或onDestroy()事件處理程序的Service。

?(4)托管正在運(yùn)行且被標(biāo)記為在前臺(tái)運(yùn)行的Service,即調(diào)用了該Service的startForeground()方法。

?(5)托管某個(gè)Service,且該Service正綁定在用戶正在交互的Activity的Service,即該Activity正處于活動(dòng)狀態(tài)。

2、可見(jiàn)進(jìn)程(visible)

? ? 沒(méi)有任何前臺(tái)組件、但仍然會(huì)影響用戶在屏幕上所見(jiàn)內(nèi)容的進(jìn)程。如果一個(gè)進(jìn)程滿足以下任一條件,即視為可見(jiàn)進(jìn)程:

(1)托管不在前臺(tái)、但仍對(duì)用戶可見(jiàn)的Activity(已調(diào)用其onPause()方法)。例如:如果前臺(tái)Acitivty啟動(dòng)了一個(gè)對(duì)話框,或者啟動(dòng)了一個(gè)非全屏,亦或是一個(gè)透明的Activity,允許在其后顯示上一個(gè)Activity,則可能會(huì)發(fā)生這種情況,這類Activity不在前臺(tái)運(yùn)行,也不能對(duì)用戶事件作出反應(yīng)。

(2)托管綁定到可見(jiàn)Activity的Service。(官網(wǎng)上說(shuō)是綁定到可見(jiàn)或前臺(tái)Activity,但筆者有一點(diǎn)疑問(wèn),這個(gè)和“前臺(tái)進(jìn)程”中第(5)點(diǎn)相矛盾嗎,綁定到前臺(tái)Activity,那就是前臺(tái)進(jìn)程了)

? ? 可見(jiàn)進(jìn)程被視為是極其重要的進(jìn)程,這類進(jìn)程的數(shù)量也很少,只有在資源極度匱乏的環(huán)境下,為保證前臺(tái)進(jìn)程繼續(xù)執(zhí)行時(shí)才會(huì)終止。

3、服務(wù)進(jìn)程(Service)

? ? 正在運(yùn)行已使用startService()方法啟動(dòng)的Serice且不屬于上述兩個(gè)更高類別進(jìn)程的進(jìn)程。盡管服務(wù)進(jìn)程與用戶所見(jiàn)內(nèi)容沒(méi)有直接關(guān)聯(lián),但是它們通常在執(zhí)行一些用戶關(guān)心的操作。因此,除非內(nèi)存不足以維持所有前臺(tái)進(jìn)程和可見(jiàn)進(jìn)程同時(shí)運(yùn)行,否則系統(tǒng)會(huì)讓服務(wù)進(jìn)程保持運(yùn)行狀態(tài)。

? ?有些資料上面也稱這種進(jìn)程為次要服務(wù)(Secondary Service),而屬于上述兩個(gè)更高類別的進(jìn)程則被稱為主要服務(wù),主要服務(wù)往往屬于系統(tǒng)進(jìn)程,如撥號(hào)進(jìn)程等,不可能被進(jìn)程管理輕易終止。這里我們以Android開(kāi)發(fā)者官網(wǎng)的稱呼為標(biāo)準(zhǔn),稱為服務(wù)進(jìn)程。

4、后臺(tái)進(jìn)程(hidden)

? ?包含目前對(duì)用戶不可見(jiàn)的Activity,即該Activity調(diào)用了onStop()方法。這些進(jìn)程對(duì)用戶體驗(yàn)沒(méi)有直接影響,系統(tǒng)可能隨時(shí)終止它們,以回收內(nèi)存供上述三個(gè)更高級(jí)別的進(jìn)程使用。通常會(huì)有很多后臺(tái)進(jìn)程在運(yùn)行,它們會(huì)保存在LRU(Least Recently Used,最近最少使用)列表中,以確保包含用戶最近查看的Activity的進(jìn)程最后一個(gè)被終止。如果某個(gè)Activity正確實(shí)現(xiàn)了生命周期方法,并保存了其當(dāng)前狀態(tài),則終止其進(jìn)程不會(huì)對(duì)用戶體驗(yàn)產(chǎn)生明顯影響,因?yàn)楫?dāng)用戶導(dǎo)航回該Activity時(shí),Activity會(huì)恢復(fù)其所有可見(jiàn)狀態(tài)。

? ?這里讀者可以做個(gè)試驗(yàn),先開(kāi)啟微信,進(jìn)入到朋友圈界面, 然后點(diǎn)擊手機(jī)屏幕下方的導(dǎo)航欄中的Home按鍵進(jìn)入到后臺(tái),再點(diǎn)擊最近使用應(yīng)用列表顯示按鈕(不同的手機(jī)位置不一樣,有的在Home鍵左邊,有的則在Home鍵右邊),在顯示的最近使用應(yīng)用的列表中清理掉微信應(yīng)用,最后再點(diǎn)擊桌面的微信圖標(biāo)啟動(dòng)微信,會(huì)發(fā)現(xiàn)顯示的界面仍然是朋友圈界面。

? ?后臺(tái)進(jìn)程,我們可以簡(jiǎn)單理解為,應(yīng)用(只考慮只有Activity組件的情況)啟動(dòng)后按Home鍵后被切換到后臺(tái)的進(jìn)程。如瀏覽器、閱讀器等,當(dāng)程序顯示在屏幕上時(shí),它們所運(yùn)行的進(jìn)程即為前臺(tái)進(jìn)程(foreground),一旦按home鍵(注意不是back鍵)返回到桌面,程序就停留在后臺(tái),成為后臺(tái)進(jìn)程。

5、空進(jìn)程(empty)

? ?不含任何活動(dòng)應(yīng)用組件的進(jìn)程。保留這種進(jìn)程的唯一目的是用作緩存,以縮短下次再其中運(yùn)行組件所需要的啟動(dòng)時(shí)間。一般來(lái)說(shuō),當(dāng)應(yīng)用按back按鍵退出后應(yīng)用后,就變成了一個(gè)空進(jìn)程。比如BTE,在程序退出后,依然會(huì)在進(jìn)程中駐留一個(gè)空進(jìn)程,這個(gè)進(jìn)程里沒(méi)有任何數(shù)據(jù)在運(yùn)行,作用往往是提高該程序下次的啟動(dòng)速度或者記錄程序的一些歷史信息。當(dāng)系統(tǒng)內(nèi)存不夠用時(shí),無(wú)疑,該進(jìn)程是應(yīng)該最先終止的。在最近使用應(yīng)用列表中,可以看到按back鍵退出的應(yīng)用。

? ?根據(jù)進(jìn)程中當(dāng)前活動(dòng)組件的重要程度,Android會(huì)將進(jìn)程評(píng)定為它可能達(dá)到的最高級(jí)別。通俗地說(shuō),就是如果一個(gè)進(jìn)程同時(shí)擁有多個(gè)對(duì)應(yīng)上述不同等級(jí)進(jìn)程的組件時(shí),會(huì)以最高的那個(gè)等級(jí)作為該進(jìn)程的等級(jí)。例如,如果某進(jìn)程托管著服務(wù)和可見(jiàn)Activity,則會(huì)將此進(jìn)程評(píng)定為可見(jiàn)進(jìn)程,而不是服務(wù)進(jìn)程。

? ?此外,一個(gè)進(jìn)程的級(jí)別可能會(huì)因?yàn)槠渌M(jìn)程對(duì)它的依賴而有所提高,即服務(wù)于另一進(jìn)程的進(jìn)程其級(jí)別永遠(yuǎn)不會(huì)低于其所服務(wù)的進(jìn)程。例如,如果進(jìn)程A中的內(nèi)容提供程序?yàn)檫M(jìn)程B中的客戶端提供服務(wù),或者如果進(jìn)程A中的服務(wù)綁定到進(jìn)程B中的組件,則進(jìn)程A始終被視為至少與進(jìn)程B同樣重要。

? ?由于運(yùn)行服務(wù)的進(jìn)程其級(jí)別高于托管后臺(tái)Activity的進(jìn)程,因此啟動(dòng)長(zhǎng)時(shí)間運(yùn)行操作的Activity最好為該操作啟動(dòng)Service,而不是簡(jiǎn)單地創(chuàng)建工作線程,當(dāng)操作有可能比Activity更加持久時(shí)更應(yīng)該如此。例如,正在將圖片上傳到網(wǎng)站的Activity應(yīng)該啟動(dòng)服務(wù)來(lái)執(zhí)行上傳,這樣一來(lái),即使用戶退出Activity,仍可在后臺(tái)繼續(xù)執(zhí)行上傳操作。使用服務(wù)可以保證,無(wú)論Activity發(fā)生什么情況,該操作至少具備“服務(wù)進(jìn)程”優(yōu)先級(jí)。如果某個(gè)Activity開(kāi)啟了線程執(zhí)行耗時(shí)操作,當(dāng)Activity退出時(shí),該Activity的實(shí)例將不會(huì)釋放內(nèi)存資源,直到線程執(zhí)行完,這樣容易導(dǎo)致內(nèi)存泄漏。同理,廣播接收器也應(yīng)該使用服務(wù),而不是簡(jiǎn)單地將耗時(shí)冗長(zhǎng)的操作放入線程中。

四、進(jìn)程移除順序的依據(jù)——閾(yu,第四聲)值

? ? 前面講到,內(nèi)存不夠用時(shí),會(huì)根據(jù)進(jìn)程的等級(jí)來(lái)決定優(yōu)先回收哪類進(jìn)程。那么系統(tǒng)是根據(jù)什么來(lái)判斷需要移除這些進(jìn)程的時(shí)機(jī)的呢?答案是閾值。

1、查看閾值

? ? 我們可以采用如下方法查看手機(jī)中各個(gè)等級(jí)進(jìn)程的閾值(需要root權(quán)限),如第二排數(shù)據(jù)所示(其單位為頁(yè)):

? ?以第一個(gè)數(shù)據(jù)44032為例,計(jì)算方法為:

? ?1page=4KB=4*1024B=4096B

? ?44032page* 4048B/page =? 180355072B

? ?180355072B/1024/1024 = 172M

? ?即第一個(gè)等級(jí)的進(jìn)程的閾值為172M。依次類推,閾值依次為:172M,190M,208M,226M,316M,415M。

? ?有必要說(shuō)明一下,在Android開(kāi)發(fā)者官方文檔中,是將Android應(yīng)用進(jìn)程分為了5個(gè)等級(jí),但很多資料卻是分的6個(gè)等級(jí),在后臺(tái)進(jìn)程和空進(jìn)程之間還有一個(gè)“內(nèi)容提供節(jié)點(diǎn)(content provider)進(jìn)程”。內(nèi)容提供節(jié)點(diǎn),沒(méi)有實(shí)體程序,僅提供內(nèi)容供別的程序去用 ,比如日歷供應(yīng)節(jié)點(diǎn),郵件供應(yīng)節(jié)點(diǎn)等,在終止進(jìn)程時(shí),這類進(jìn)程有比較高的優(yōu)先權(quán)。手機(jī)中應(yīng)該是采用的6個(gè)等級(jí)的方式,如上六個(gè)數(shù)據(jù),正好對(duì)應(yīng)著六個(gè)等級(jí)的進(jìn)程,等級(jí)越高,閾值越低,即前臺(tái)進(jìn)程閾值為172M,空進(jìn)程為415M。當(dāng)系統(tǒng)的剩余內(nèi)存只剩余不到415M的時(shí)候,系統(tǒng)首先會(huì)回收空進(jìn)程,依次類推,只有剩余內(nèi)存不到172M了,才會(huì)去回收前臺(tái)進(jìn)程,這樣就起到了優(yōu)化保護(hù)重要進(jìn)程的作用。

五、Home鍵、Back鍵和多任務(wù)鍵

? ?Home鍵、Back鍵和多任務(wù)鍵,在手機(jī)屏幕的下方,這三個(gè)按鍵一般稱為導(dǎo)航欄,中間的按鈕為Home鍵,多任務(wù)鍵和Back鍵分別在其左右,一般根據(jù)手機(jī)品牌不同,左右位置也有所差異。

? ?在運(yùn)行App的時(shí)候,如果按一下Home鍵或者Back鍵,都可以退到桌面,那么這兩者有什么區(qū)別呢?

Home鍵。按Home鍵的時(shí)候,App如果沒(méi)有Service開(kāi)啟,會(huì)從一個(gè)前臺(tái)進(jìn)程轉(zhuǎn)變?yōu)橐粋€(gè)后臺(tái)進(jìn)程;如果有前臺(tái)service運(yùn)行,就仍然是前臺(tái)進(jìn)程,比如QQ音樂(lè)播放器等;如果是只有普通service運(yùn)行,那么就轉(zhuǎn)變?yōu)榉?wù)進(jìn)程(參照前文中講的Android進(jìn)程的5個(gè)級(jí)別)。

Back鍵。按Back鍵的時(shí)候,App如果沒(méi)有Service開(kāi)啟,會(huì)從一個(gè)前臺(tái)進(jìn)程轉(zhuǎn)變?yōu)橐粋€(gè)空進(jìn)程;對(duì)于有Service運(yùn)行的情況,和按Home鍵一樣。

? ? 后臺(tái)進(jìn)程和空進(jìn)程,都是駐留在后臺(tái),處于暫停狀態(tài),也都是除了占用一部分內(nèi)存外,不占用其他如cpu等資源的,那么問(wèn)題來(lái)了,為什么要設(shè)計(jì)后臺(tái)進(jìn)程和空進(jìn)程這兩種空進(jìn)程呢?它們的區(qū)別到底在哪里呢?我們?cè)谇拔闹vAndroid進(jìn)程的5個(gè)等級(jí)的時(shí)候講到過(guò),當(dāng)剩余內(nèi)存不足的時(shí)候,系統(tǒng)會(huì)按照等級(jí)順序,優(yōu)先移除不太重要進(jìn)程,以收回內(nèi)存供更重要的進(jìn)程運(yùn)行。那么,它們的區(qū)別就是,在剩余內(nèi)存不足時(shí),會(huì)優(yōu)先移除空進(jìn)程,再不足,才會(huì)移除空進(jìn)程。所以,如果確實(shí)要退出某個(gè)應(yīng)用一段時(shí)間內(nèi)不大使用了,如果這款應(yīng)用有退出按鈕,就用應(yīng)用自帶的退出功能;如果沒(méi)有,則最好按系統(tǒng)的Back鍵,這樣可以變成空進(jìn)程,當(dāng)系統(tǒng)要回收內(nèi)存時(shí),就會(huì)優(yōu)先被回收,從而釋放的所占的資源。如果只是暫時(shí)退出去做點(diǎn)別的,過(guò)一會(huì)還要切換回來(lái),或者對(duì)這款應(yīng)用使用比較頻繁,那就使用Home鍵,因?yàn)橄啾扔诎碆ack鍵,這樣可以盡可能保住后臺(tái)進(jìn)程,方便下次使用的時(shí)候快速啟動(dòng)。

? ?當(dāng)然,按Home鍵或Back鍵,對(duì)用戶來(lái)說(shuō),其實(shí)感覺(jué)不到差異,使用起來(lái)沒(méi)什么兩樣,但是,對(duì)于Android開(kāi)發(fā)者來(lái)說(shuō),卻有必要作為常識(shí)來(lái)了解其中的道理和差異。無(wú)論是按Home鍵還是按Back鍵,在按多任務(wù)鍵的時(shí)候,都可以看到這些進(jìn)程,如下圖所示。最下面的按鍵為清理按鍵,點(diǎn)擊后可以清除掉這些進(jìn)程,回收內(nèi)存了,當(dāng)然,前面也講了很多遍了,不建議這樣做。

2、修改閾值。

? ?可以采用命令:echo "44032,48640,53248,57856,80896,106241" /sys/module/lowmemorykiller/parameters/minfree來(lái)修改閾值,如下所示:

? ?重啟后,會(huì)恢復(fù)為原來(lái)的值。至于如何永久性修改該閾值,這里不深入探討,有興趣的童鞋可以自行研究,一般來(lái)說(shuō),就按照系統(tǒng)給定的默認(rèn)值使用就可以了,沒(méi)特殊用途的話,沒(méi)必要修改。

? ?對(duì)于這一節(jié)閾值的內(nèi)容,暫時(shí)先講到這里,如果要更深入,可以自行多研究研究。筆者也沒(méi)有看到比較好的更深入的文章,所以也不好推薦,如果讀者看到比較好的,可以推薦給筆者,感激不盡。

六、開(kāi)發(fā)者選項(xiàng)中的進(jìn)程管理功能

? ? Android手機(jī)都帶有開(kāi)發(fā)者選項(xiàng),隱藏了很多功能,顧名思義,這些功能主要用于輔助開(kāi)發(fā)者調(diào)試程序用的。其中有一些就是關(guān)于進(jìn)程管理功能的,筆者這里簡(jiǎn)單介紹一下其中兩款,如下圖紅框部分所示:

不保留活動(dòng)。用戶離開(kāi)以后即銷毀每個(gè)活動(dòng)(Activity),這樣做使得后臺(tái)進(jìn)程都被銷毀了。筆者試驗(yàn)過(guò)幾款app,比如微信,瀏覽器,開(kāi)啟/關(guān)閉“不保留活動(dòng)”前后,按Home鍵后,再打開(kāi)應(yīng)用,有明顯的差別。當(dāng)然,也試用了短信,DD打車,就沒(méi)看出起了什么作用。讀者若是感興趣可以深入研究研究,到時(shí)候在指導(dǎo)指導(dǎo)筆者!

后臺(tái)進(jìn)程限制。如下圖所示,給出了后臺(tái)進(jìn)程個(gè)數(shù)限制的選項(xiàng)。

七、進(jìn)程管理軟件的使用

? ?Windows操作系統(tǒng)用戶往往總想著保留更多的內(nèi)存,在使用Android手機(jī)的時(shí)候,喜歡經(jīng)常清理后臺(tái)進(jìn)程或空進(jìn)程,而且清理完后,心里有一種特別爽的感覺(jué),就像給家里做了一次大掃除一樣,筆者最初使用Android手機(jī)的時(shí)候也是這樣的心態(tài)-_-!基于這樣的心態(tài),一些進(jìn)程清理軟件,很受普通用戶的青睞。其實(shí)這樣做卻正好抹殺了Android系統(tǒng)所標(biāo)榜的優(yōu)勢(shì),如前文所講到的。

? ?那么進(jìn)程管理軟件有無(wú)必要呢?當(dāng)然有的,只是需要注意使用場(chǎng)合。當(dāng)需要運(yùn)行大型程序的時(shí)候,可以手動(dòng)關(guān)閉掉一些進(jìn)程,騰出足夠的空間供大型程序使用,這樣就可以有效避免系統(tǒng)調(diào)用進(jìn)程調(diào)度策略而引起的卡頓,這一點(diǎn),第八大點(diǎn)第3小節(jié)中會(huì)有說(shuō)明。而且由于開(kāi)發(fā)者的原因,可能是程序?qū)懙锰珷€,或程序容易出錯(cuò),或做不該做的動(dòng)作,或是惡意程序,對(duì)于這類程序進(jìn)程,手動(dòng)移除也是有好處的。

? ?但如果是運(yùn)行一些小程序,就完全沒(méi)有必要去預(yù)先殺進(jìn)程了,完全可以交給系統(tǒng)自己管理。讀者可能會(huì)疑惑,因?yàn)樾〕绦騿?dòng)的時(shí)候,也有可能會(huì)因?yàn)閮?nèi)存不足而導(dǎo)致需要移除部分進(jìn)程的情況。筆者認(rèn)為,即便是內(nèi)存不足,小程序運(yùn)行引起的調(diào)用進(jìn)程調(diào)度策略測(cè)的次數(shù)非常少,要移除的進(jìn)程也非常少,產(chǎn)生的影響不大。同時(shí),我們也要意識(shí)到另外一點(diǎn)就是,無(wú)論是手動(dòng)殺死進(jìn)程還是自動(dòng)殺進(jìn)程,都需要cpu去執(zhí)行這些任務(wù),所以也會(huì)拖慢手機(jī)和消耗電量。所以從這一點(diǎn)看,頻繁殺進(jìn)程,也是一個(gè)不好的習(xí)慣。

八、答疑解惑

? ? 在以前沒(méi)有專門去了解Android進(jìn)程管理機(jī)制的時(shí)候,甚至是在研究的過(guò)程中,筆者心里都經(jīng)常存在很多疑惑,以下整理了其中5個(gè),不知道讀者您是否有也類似的困惑呢?

1、這么多駐留在內(nèi)存的進(jìn)程,不會(huì)耗電嗎?

? ?大多數(shù)用慣了Windows操作系統(tǒng)的童鞋,看到Android系統(tǒng)盡可能保留不在活動(dòng)的進(jìn)程的設(shè)計(jì),可能第一反應(yīng)就是質(zhì)疑,難道這樣不會(huì)增加耗電量嗎?其實(shí),但一個(gè)程序按home鍵變成后臺(tái)進(jìn)程或者按back鍵退出變成空進(jìn)程后,其實(shí)已經(jīng)被暫停了,只保留了運(yùn)行狀態(tài),不會(huì)消耗cpu,一個(gè)程序會(huì)耗電,是因?yàn)樗枰{(diào)用cpu來(lái)運(yùn)算,現(xiàn)在不消耗cpu了,當(dāng)然就不會(huì)耗電了。當(dāng)然,開(kāi)了service的應(yīng)用就另當(dāng)別論了,比如QQ音樂(lè)播放器,當(dāng)按home鍵或back鍵后,音樂(lè)仍然播放,是因?yàn)樗_(kāi)啟了服務(wù),而且是一個(gè)前臺(tái)服務(wù),在后面我們會(huì)繼續(xù)講到,此時(shí)它是一個(gè)前臺(tái)進(jìn)程,而不是后臺(tái)進(jìn)程或空進(jìn)程。

2、為什么一個(gè)不太app,運(yùn)行時(shí)會(huì)占用很大的內(nèi)存呢?

我們經(jīng)常會(huì)碰到這樣一種現(xiàn)象,一個(gè)只有20M的App,運(yùn)行起來(lái)的時(shí)候,卻會(huì)耗掉100M以上的內(nèi)存。一方面是,程序運(yùn)行時(shí)為對(duì)象分配內(nèi)存,另一方面,是Android虛擬機(jī)的原因。Android中的應(yīng)用啟動(dòng)的時(shí)候,系統(tǒng)都會(huì)給它開(kāi)啟一個(gè)獨(dú)立的虛擬機(jī),這樣做的好處是可以避免虛擬機(jī)崩潰導(dǎo)致整個(gè)系統(tǒng)崩潰,代價(jià)就是耗用更多的內(nèi)存。

3、為什么內(nèi)存少的時(shí)候,運(yùn)行大型程序會(huì)卡頓呢?

? ? 當(dāng)剩余內(nèi)存不多時(shí),打開(kāi)大型程序,系統(tǒng)會(huì)觸發(fā)自身的進(jìn)程調(diào)度策略,去移除一些等級(jí)比較低的進(jìn)程來(lái)回收內(nèi)存,以供大型程序運(yùn)行。而這個(gè)進(jìn)程調(diào)度策略在決定哪些進(jìn)程需要被移除的過(guò)程,是一個(gè)十分消耗資源的操作,特別是一個(gè)程序頻繁像系統(tǒng)申內(nèi)存的時(shí)候,這樣就導(dǎo)致了系統(tǒng)的卡頓。

4、應(yīng)用開(kāi)得太多了,手機(jī)變慢,是因?yàn)閮?nèi)存被占用太多嗎?

? ? 其實(shí)手機(jī)變慢的根本原因是cpu被耗用太多,而不是內(nèi)存占用太多,因?yàn)檎嬲龍?zhí)行程序所要完成的任務(wù)的最終執(zhí)行者是CPU,而不是內(nèi)存(RAM)。在內(nèi)存足夠的情況下,如果系統(tǒng)中占用cpu的進(jìn)程太多,那無(wú)疑cpu總有忙不過(guò)來(lái)的時(shí)候,那肯定就會(huì)變慢了。這就好比,在一條道路上駕車,道路就像內(nèi)存,車的引擎就像cpu,如果車的引擎的動(dòng)力不夠,或者承載的貨物太多,車都跑不快,即便是道路上一路暢通無(wú)阻,也無(wú)濟(jì)于事。所以,內(nèi)存占用多少并不重要,只要道路提供給車輛前行的空間是足夠的,手機(jī)變慢的責(zé)任,就和內(nèi)存無(wú)關(guān)了。這個(gè)比喻用來(lái)解釋第三點(diǎn)也很恰當(dāng),道路提供的車輛前進(jìn)的空間無(wú)法滿足車輛所必需的空間時(shí),就需要交通機(jī)制花時(shí)間來(lái)調(diào)節(jié)交通,給這輛車提供足夠的空間,而在此期間,這輛車只能乖乖候著。

5、Android手機(jī)越用越慢,是什么原因呢?

Android手機(jī)常常是越用越慢,即使是恢復(fù)出廠設(shè)置,也無(wú)法改變這個(gè)現(xiàn)象。手機(jī)越用越慢,主要由如下幾個(gè)原因:(1)虛擬機(jī)機(jī)制問(wèn)題。這一點(diǎn)在上一個(gè)問(wèn)題中也提到了,在Android4.4以前的系統(tǒng),使用的是Dalvik虛擬機(jī),它的設(shè)計(jì)機(jī)制有缺陷,就是越用越慢;在Android4.4系統(tǒng)中有切換按鈕,可以在Art虛擬機(jī)和Dalvik虛擬機(jī)之間切換;在Android4.4以后的系統(tǒng)就徹底拋棄了Dalvik而全面使用Art。(2)開(kāi)啟了太多的服務(wù),導(dǎo)致耗用太多的CPU。隨著手機(jī)開(kāi)機(jī)使用時(shí)間的增長(zhǎng),應(yīng)用使用越來(lái)越多,很多應(yīng)用看似退出了,而其實(shí)后臺(tái)可能開(kāi)了不少的服務(wù),而他們可能還沒(méi)有關(guān)閉。這些服務(wù)正在執(zhí)行一些操作,會(huì)消耗CPU,而CPU才是手機(jī)變慢的根本原因。 而且Android app比較開(kāi)放的,有很多不良應(yīng)用充斥其中,可能對(duì)服務(wù)處理不當(dāng),濫用服務(wù)等,增加系統(tǒng)中的服務(wù)。(3)系統(tǒng)頻繁調(diào)用自身的進(jìn)程調(diào)度算法。這一點(diǎn)在前面已經(jīng)說(shuō)明了,這里不再贅述。(4)手機(jī)硬件的自然老化

Android 進(jìn)程和線程的區(qū)別

·有一段程序供其執(zhí)行

·擁有專用的系統(tǒng)堆棧空間

·在內(nèi)存中有對(duì)應(yīng)的進(jìn)程控制塊

·擁有獨(dú)立的用戶存儲(chǔ)空間

·進(jìn)程之間不能進(jìn)行自由的信息交互(別問(wèn)我,問(wèn)就是Android規(guī)定的)

·每個(gè)進(jìn)程必須包含一個(gè)線程

·進(jìn)程間的切換開(kāi)銷比較大,線程創(chuàng)建和終止比進(jìn)程快,進(jìn)程間無(wú)法進(jìn)行自由的資源交換,同進(jìn)程內(nèi)的線程可以自由交換

我們可以將Android系統(tǒng)比做一個(gè)大公司,進(jìn)程相當(dāng)于某個(gè)部門的經(jīng)理,他有自己要做到項(xiàng)目(有一段程序供其執(zhí)行,在內(nèi)存中有對(duì)應(yīng)的進(jìn)程控制塊),擁有自己部門的辦公場(chǎng)地(擁有獨(dú)立的用戶存儲(chǔ)空間)。

線程就相當(dāng)于每個(gè)部門的員工,員工得依賴于經(jīng)理提供的工作環(huán)境才能夠進(jìn)行工作(線程必須依賴于進(jìn)程),而經(jīng)理手下必須得有一個(gè)員工(要不然分配的工作交給誰(shuí)來(lái)做),我們都知道在一個(gè)大公司下每個(gè)部門和每個(gè)部門溝通是比較困難的,但是一個(gè)部門之間的員工溝通相對(duì)容易許多(同進(jìn)程下的線程共享資源)。

參考:

Android 如何進(jìn)行進(jìn)程保活

每一個(gè) Android 應(yīng)用啟動(dòng)后至少對(duì)應(yīng)一個(gè)進(jìn)程,有的是多個(gè)進(jìn)程,而且主流應(yīng)用中多個(gè)

進(jìn)程的應(yīng)用比例較大

對(duì)于任何一個(gè)進(jìn)程,我們都可以通過(guò) adb shell ps|grep package_name的方式來(lái)查看

它的基本信息

Android 中的進(jìn)程跟封建社會(huì)一樣,分了三流九等,Android 系統(tǒng)把進(jìn)程的劃為了如下

幾種(重要性從高到低),網(wǎng)上多位大神都詳細(xì)總結(jié)過(guò)(備注:嚴(yán)格來(lái)說(shuō)是劃分了 6 種)。

場(chǎng)景:

1.某個(gè)進(jìn)程持有一個(gè)正在與用戶交互的 Activity 并且該 Activity 正處于 resume 的

狀態(tài)。

2.某個(gè)進(jìn)程持有一個(gè) Service,并且該 Service 與用戶正在交互的 Activity 綁定。

3.某個(gè)進(jìn)程持有一個(gè) Service,并且該 Service 調(diào)用 startForeground()方法使之位于前臺(tái)運(yùn)行。

4.某個(gè)進(jìn)程持有一個(gè) Service,并且該 Service 正在執(zhí)行它的某個(gè)生命周期回調(diào)方法,比如 onCreate()、 onStart()或 onDestroy()。

5.某個(gè)進(jìn)程持有一個(gè) BroadcastReceiver,并且該 BroadcastReceiver 正在執(zhí)行其onReceive()方法。用戶正在使用的程序,一般系統(tǒng)是不會(huì)殺死前臺(tái)進(jìn)程的,除非用戶強(qiáng)制停止應(yīng)用或者系統(tǒng)內(nèi)存不足等極端情況會(huì)殺死。

場(chǎng)景:

1.擁有不在前臺(tái)、但仍對(duì)用戶可見(jiàn)的 Activity(已調(diào)用 onPause())。

2.擁有綁定到可見(jiàn)(或前臺(tái))Activity 的 Service

用戶正在使用,看得到,但是摸不著,沒(méi)有覆蓋到整個(gè)屏幕,只有屏幕的一部分可見(jiàn)進(jìn)程

不包含任何前臺(tái)組件,一般系統(tǒng)也是不會(huì)殺死可見(jiàn)進(jìn)程的,除非要在資源吃緊的情況下,

要保持某個(gè)或多個(gè)前臺(tái)進(jìn)程存活

場(chǎng)景

1.某個(gè)進(jìn)程中運(yùn)行著一個(gè) Service 且該 Service 是通過(guò) startService()啟動(dòng)的,與用戶看見(jiàn)的界面沒(méi)有直接關(guān)聯(lián)。

在內(nèi)存不足以維持所有前臺(tái)進(jìn)程和可見(jiàn)進(jìn)程同時(shí)運(yùn)行的情況下,服務(wù)進(jìn)程會(huì)被殺死

場(chǎng)景:

在用戶按了"back"或者"home"后,程序本身看不到了,但是其實(shí)還在運(yùn)行的程序,

比如 Activity 調(diào)用了 onPause 方法系統(tǒng)可能隨時(shí)終止它們,回收內(nèi)存

場(chǎng)景:

某個(gè)進(jìn)程不包含任何活躍的組件時(shí)該進(jìn)程就會(huì)被置為空進(jìn)程,完全沒(méi)用,殺了它只有好處沒(méi)壞處,第一個(gè)干它!

上面是進(jìn)程的分類,進(jìn)程是怎么被殺的呢?系統(tǒng)出于體驗(yàn)和性能上的考慮,app 在退到

后臺(tái)時(shí)系統(tǒng)并不會(huì)真正的 kill 掉這個(gè)進(jìn)程,而是將其緩存起來(lái)。打開(kāi)的應(yīng)用越多,后臺(tái)緩存的進(jìn)程也越多。在系統(tǒng)內(nèi)存不足的情況下,系統(tǒng)開(kāi)始依據(jù)自身的一套進(jìn)程回收機(jī)制

來(lái)判斷要 kill 掉哪些進(jìn)程,以騰出內(nèi)存來(lái)供給需要的 app, 這套殺進(jìn)程回收內(nèi)存的機(jī)制

就叫 Low Memory Killer。那這個(gè)不足怎么來(lái)規(guī)定呢,那就是內(nèi)存閾值,我們可以使用

cat /sys/module/lowmemorykiller/parameters/minfree 來(lái)查看某個(gè)手機(jī)的內(nèi)存閾值。

其實(shí)系統(tǒng)在進(jìn)程回收跟內(nèi)存回收類似也是有一套嚴(yán)格的策略,可以

自己去了解,大概是這個(gè)樣子的,oom_adj 越大,占用物理內(nèi)存越多會(huì)被最先 kill 掉,OK,那么現(xiàn)在對(duì)于進(jìn)程如何?;钸@個(gè)問(wèn)題就轉(zhuǎn)化成,如何降低 oom_adj 的值,以及如

何使得我們應(yīng)用占的內(nèi)存最少。

據(jù)說(shuō)這個(gè)是手 Q 的進(jìn)程?;罘桨?,基本思想,系統(tǒng)一般是不會(huì)殺死前臺(tái)進(jìn)程的。所以要

使得進(jìn)程常駐,我們只需要在鎖屏的時(shí)候在本進(jìn)程開(kāi)啟一個(gè) Activity,為了欺騙用戶,

讓這個(gè) Activity 的大小是 1 像素,并且透明無(wú)切換動(dòng)畫,在開(kāi)屏幕的時(shí)候,把這個(gè) Activity

關(guān)閉掉,所以這個(gè)就需要監(jiān)聽(tīng)系統(tǒng)鎖屏廣播,我試過(guò)了,的確好使,如下。

如果直接啟動(dòng)一個(gè) Activity,當(dāng)我們按下 back 鍵返回桌面的時(shí)候,oom_adj 的值是 8,

上面已經(jīng)提到過(guò),這個(gè)進(jìn)程在資源不夠的情況下是容易被回收的。現(xiàn)在造一個(gè)一個(gè)像素

的 Activity。

為了做的更隱藏,最好設(shè)置一下這個(gè) Activity 的主題,當(dāng)然也無(wú)所謂了

在屏幕關(guān)閉的時(shí)候把 LiveActivity 啟動(dòng)起來(lái),在開(kāi)屏的時(shí)候把 LiveActivity 關(guān)閉掉,所以

要監(jiān)聽(tīng)系統(tǒng)鎖屏廣播,以接口的形式通知 MainActivity 啟動(dòng)或者關(guān)閉 LiveActivity。

現(xiàn)在 MainActivity 改成如下

按下 back 之后,進(jìn)行鎖屏,現(xiàn)在測(cè)試一下 oom_adj 的值

果然將進(jìn)程的優(yōu)先級(jí)提高了。

但是還有一個(gè)問(wèn)題,內(nèi)存也是一個(gè)考慮的因素,內(nèi)存越多會(huì)被最先 kill 掉,所以把上面

的業(yè)務(wù)邏輯放到 Service 中,而 Service 是在另外一個(gè) 進(jìn)程中,在 MainActivity 開(kāi)啟這

個(gè)服務(wù)就行了,這樣這個(gè)進(jìn)程就更加的輕量,

OK,通過(guò)上面的操作,我們的應(yīng)用就始終和前臺(tái)進(jìn)程是一樣的優(yōu)先級(jí)了,為了省電,

系統(tǒng)檢測(cè)到鎖屏事件后一段時(shí)間內(nèi)會(huì)殺死后臺(tái)進(jìn)程,如果采取這種方案,就可以避免了

這個(gè)問(wèn)題。但是還是有被殺掉的可能,所以我們還需要做雙進(jìn)程守護(hù),關(guān)于雙進(jìn)程守護(hù),

比較適合的就是 aidl 的那種方式,但是這個(gè)不是完全的靠譜,原理是 A 進(jìn)程死的時(shí)候,

B 還在活著,B 可以將 A 進(jìn)程拉起來(lái),反之,B 進(jìn)程死的時(shí)候,A 還活著,A 可以將 B

拉起來(lái)。所以雙進(jìn)程守護(hù)的前提是,系統(tǒng)殺進(jìn)程只能一個(gè)個(gè)的去殺,如果一次性殺兩個(gè),

這種方法也是不 OK 的。

事實(shí)上

那么我們先來(lái)看看 Android5.0 以下的源碼,ActivityManagerService 是如何關(guān)閉在應(yīng)用

退出后清理內(nèi)存的

在應(yīng)用退出后,ActivityManagerService 不僅把主進(jìn)程給殺死,另外把主進(jìn)程所屬的進(jìn)

程組一并殺死,這樣一來(lái),由于子進(jìn)程和主進(jìn)程在同一進(jìn)程組,子進(jìn)程在做的事情,也

就停止了。所以在 Android5.0 以后的手機(jī)應(yīng)用在進(jìn)程被殺死后,要采用其他方案。

這種大部分人都了解,據(jù)說(shuō)這個(gè)微信也用過(guò)的進(jìn)程保活方案,移步微信 Android 客戶端

后臺(tái)保活經(jīng)驗(yàn)分享,這方案實(shí)際利用了 Android 前臺(tái) service 的漏洞。

原理如下

對(duì)于 API level 18 :調(diào)用 startForeground(ID, new Notification()),發(fā)送空的

Notification ,圖標(biāo)則不會(huì)顯示。

對(duì)于 API level = 18:在需要提優(yōu)先級(jí)的 service A 啟動(dòng)一個(gè) InnerService,兩個(gè)服務(wù)

同時(shí) startForeground,且綁定同樣的 ID。Stop 掉 InnerService ,這樣通知欄圖標(biāo)即

被移除。

public class KeepLiveService extends Service{

public static final int NOTIFICATION_ID=0x11;?

public KeepLiveService() {

}

@Override

public IBinder onBind(Intent intent){

throw new UnsupportedOperationException("Not yet implemented");

}

@Override?

public void onCreate() {

super.onCreate(); //API 18 以下,直 接發(fā) 送 Notification 并 將 其 置 為 前 臺(tái)

if(Build.VERSION.SDK_INTBuild.VERSION_CODES.JELLY_BEAN_MR2){

startForeground(NOTIFICATION_ID,new Notification());?

} else { //API 18 以上,發(fā)送 Notification 并將其置為前臺(tái)后,啟動(dòng) InnerService

Notification.Builder builder=new Notification.Builder(this);

builder.setSmallIcon(R.mipmap.ic_launcher);

startForeground(NOTIFICATION_ID, builder.build());

startService(new Intent(this, InnerService.class));

}

}

public class InnerService extends Service{

@Override public IBinder onBind(Intent intent) {

return null;

}?

@Override public void onCreate() {

super.onCreate(); //發(fā)送與 KeepLiveService中 ID 相同的 Notification,然后將其取消并取消自己的前臺(tái)顯示

Notification.Builder builder = new Notification.Builder(this);

builder.setSmallIcon(R.mipmap.ic_launcher);startForeground(NOTIFICATION_ID,

builder.build());

new Handler().postDelayed(new Runnable() {?

@Override public void run() {?

stopForeground(true);

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

manager.cancel(NOTIFICATION_ID);?

stopSelf();

}

},

100);

}

}

}

在沒(méi)有采取前臺(tái)服務(wù)之前,啟動(dòng)應(yīng)用,oom_adj 值是 0,按下返回鍵之后,變成 9(不

同 ROM 可能不一樣)

相互喚醒的意思就是,假如你手機(jī)里裝了支付寶、淘寶、天貓、UC 等阿里系的 app,

那么你打開(kāi)任意一個(gè)阿里系的 app 后,有可能就順便把其他阿里系的 app 給喚醒了。

這個(gè)完全有可能的。此外,開(kāi)機(jī),網(wǎng)絡(luò)切換、拍照、拍視頻時(shí)候,利用系統(tǒng)產(chǎn)生的廣播

也能喚醒 app,不過(guò) Android N 已經(jīng)將這三種廣播取消了。

如果應(yīng)用想?;?,要是 QQ,微信愿意救你也行,有多少手機(jī)上沒(méi)有 QQ,微信呢?或

者像友盟,信鴿這種推送 SDK,也存在喚醒 app 的功能。

拉活方法

JobSheduler是作為進(jìn)程死后復(fù)活的一種手段,

native進(jìn)程方式最大缺點(diǎn)是費(fèi)電,Native

進(jìn)程費(fèi)電的原因是感知主進(jìn)程是否存活有兩種實(shí)現(xiàn)方式,在 Native 進(jìn)程中通過(guò)死循環(huán)

或定時(shí)器,輪訓(xùn)判斷主進(jìn)程是否存活,當(dāng)主進(jìn)程不存活時(shí)進(jìn)行拉活。其次 5.0 以上系統(tǒng)

不支持。 但是 JobSheduler 可以替代在 Android5.0 以上 native 進(jìn)程方式,這種方式即

使用戶強(qiáng)制關(guān)閉,也能被拉起來(lái),親測(cè)可行。

JobSheduler@TargetApi(Build.VERSION_CODES.LOLLIPOP)?

public class MyJobService extends JobService {

@Override

public void onCreate() {

super.onCreate();

startJobSheduler();

}

public void startJobSheduler() {?

try {

JobInfo.Builder builder = new JobInfo.Builder(1,new ComponentName(getPackageName(), MyJobService.class.getName()));

builder.setPeriodic(5); builder.setPersisted(true); JobScheduler jobScheduler =(JobScheduler)

this.getSystemService(Context.JOB_SCHEDULER_SERVICE);

jobScheduler.schedule(builder.build());

}

catch

(Exception ex)

{ ex.printStackTrace(); } }

@Override?

public boolean onStartJob(JobParameters jobParameters) {

return false;?

} @Override public boolean onStopJob(JobParameters jobParameters) {?

return false;?

}

}

這個(gè)是系統(tǒng)自帶的,onStartCommand 方法必須具有一個(gè)整形的返回值,這個(gè)整形的返

回值用來(lái)告訴系統(tǒng)在服務(wù)啟動(dòng)完畢后,如果被 Kill,系統(tǒng)將如何操作,這種方案雖然可

以,但是在某些情況 or 某些定制 ROM 上可能失效,我認(rèn)為可以多做一種保保守方案。

1.START_STICKY

如果系統(tǒng)在 onStartCommand 返回后被銷毀,系統(tǒng)將會(huì)重新創(chuàng)建服務(wù)并依次調(diào)用

onCreate 和 onStartCommand(注意:根據(jù)測(cè)試 Android2.3.3 以下版本只會(huì)調(diào)用

onCreate 根本不會(huì)調(diào)用 onStartCommand,Android4.0 可以辦到),這種相當(dāng)于服務(wù)

又重新啟動(dòng)恢復(fù)到之前的狀態(tài)了)。

2.START_NOT_STICKY

如果系統(tǒng)在 onStartCommand 返回后被銷毀,如果返回該值,則在執(zhí)行完

onStartCommand 方法后如果 Service 被殺掉系統(tǒng)將不會(huì)重啟該服務(wù)

3.START_REDELIVER_INTENT

START_STICKY 的兼容版本,不同的是其不保證服務(wù)被殺后一定能重啟。

4.相比與粘性服務(wù)與系統(tǒng)服務(wù)捆綁更厲害一點(diǎn),這個(gè)來(lái)自愛(ài)哥的研究,這里說(shuō)的系統(tǒng)服務(wù)

很好理解,比如 NotificationListenerService,NotificationListenerService 就是一個(gè)監(jiān)聽(tīng)

通知的服務(wù),只要手機(jī)收到了通知,NotificationListenerService 都能監(jiān)聽(tīng)到,即時(shí)用戶

把進(jìn)程殺死,也能重啟,所以說(shuō)要是把這個(gè)服務(wù)放到我們的進(jìn)程之中,那么就可以呵呵

所以你的應(yīng)用要是有消息推送的話,那么可以用這種方式去欺騙用戶。

Android 進(jìn)程管理篇(五)-調(diào)度策略與優(yōu)先級(jí)

接上篇cpuset,這篇來(lái)看看進(jìn)程優(yōu)先級(jí)與調(diào)度策略管理。

Linux中,優(yōu)先級(jí)號(hào)一共有0-139,其中0-99的是RT(實(shí)時(shí))進(jìn)程,100-139的是非實(shí)時(shí)進(jìn)程。

數(shù)字越低優(yōu)先級(jí)越高。

SCHED_IDLE idle狀態(tài)低優(yōu)先級(jí)進(jìn)程調(diào)度

先看Process中調(diào)度策略的劃分,與上面介紹的一樣。

首先在AMS中封裝了FIFO和NORMAL的兩個(gè)策略,NORMAL好說(shuō),看看FIFO在哪用到

這里Process.setThreadScheduler并沒(méi)有太多的應(yīng)用,我們直接來(lái)看優(yōu)先級(jí)設(shè)置吧。else中將top app的UI線程與render線程都設(shè)置為TOP_APP_PRIORITY_BOOST優(yōu)先級(jí),nice值為-10,非常高。

這里主要調(diào)用androidSetThreadPriority方法

這里通過(guò)set_sched_policy來(lái)調(diào)整調(diào)度策略,并通過(guò)setpriority設(shè)置進(jìn)程優(yōu)先級(jí)。這里不特意區(qū)分進(jìn)程與線程了,反正在linux中都是進(jìn)程。

這里與前面的cpuset非常相似,依然是寫節(jié)點(diǎn),節(jié)點(diǎn)前面也提了就是:

那么這里又引入了一個(gè)schedtune子系統(tǒng),簡(jiǎn)單介紹下:

schedtune是ARM/Linaro為了EAS新增的一個(gè)子系統(tǒng),主要用來(lái)控制進(jìn)程調(diào)度選擇CPU以及boost觸發(fā)。通過(guò)權(quán)重來(lái)分配CPU負(fù)載能力來(lái)實(shí)現(xiàn)快速運(yùn)行。高權(quán)重意味著會(huì)享受到更好的cpu負(fù)載來(lái)處理對(duì)應(yīng)的任務(wù),換句話說(shuō)你能享受相對(duì)更好的cpu運(yùn)行性能。

簡(jiǎn)單梳理下schedtune和不同類型SchedPolicy之間的對(duì)應(yīng)關(guān)系:

看下具體文件夾內(nèi)容:

系統(tǒng)配置:

這里/dev/stune相關(guān)配置只做了這么一個(gè)

Android 如何最大限度的?;詈笈_(tái)進(jìn)程

前言:本文將通過(guò)兩種方式,在手機(jī)亮屏和屏鎖狀態(tài)下聯(lián)合對(duì)進(jìn)程進(jìn)行?;?。

一、手機(jī)亮屏?xí)r如何提高存活率

在點(diǎn)擊home鍵使app長(zhǎng)時(shí)間停留在后臺(tái)時(shí),內(nèi)存不足時(shí)會(huì)被殺死。

處理這種情況時(shí)運(yùn)用灰色?;?,在service里通過(guò)Service.startForeground() 設(shè)置為前臺(tái)服務(wù),提高存活率。

GrayInnerService

二、手機(jī)鎖屏?xí)r如何提高存活率

手機(jī)在進(jìn)入鎖屏狀態(tài)一段時(shí)間,省電機(jī)制會(huì)殺死后臺(tái)進(jìn)程。

處理這種情況時(shí),我們需注冊(cè)廣播監(jiān)聽(tīng)鎖屏和解鎖事件, 鎖屏后啟動(dòng)一個(gè)1像素的透明Activity, 解鎖后銷毀這個(gè)透明Activity。

注:這個(gè)廣播要寫到要保活的service中。

OnePiexlActivity.class

總結(jié):以上就是在手機(jī)鎖屏和亮屏?xí)r對(duì)進(jìn)程進(jìn)行?;畹膬煞N方法

源碼地址:

人人都應(yīng)該了解的 Android 進(jìn)程管理機(jī)制

打開(kāi)設(shè)置--應(yīng)用與服務(wù)(不同機(jī)型進(jìn)入方式可能不同),你就會(huì)看到當(dāng)前正在運(yùn)行的進(jìn)程和服務(wù),也就是目前正在“后臺(tái)運(yùn)行”的任務(wù)。列表中有你剛剛使用過(guò)的 APP ,也有一兩小時(shí)前打開(kāi)過(guò)的 APP。還有一些軟件你甚至不知道自己什么時(shí)候打開(kāi)過(guò)(其實(shí)根本就不是自己打開(kāi)的),或者記得自己已經(jīng)“關(guān)閉”了,但它們也在列表中,消耗著你的手機(jī)資源。列表中有一些條目名字很奇怪,一般人看不懂,但還是覺(jué)得“它很重要”,不敢輕易強(qiáng)制關(guān)閉。這個(gè)列表展示的內(nèi)容和普通的后臺(tái)管理界面不太一樣,感覺(jué)稍稍有些神秘,然而這又是我們?nèi)粘J褂盟乇懿涣说囊徊糠帧?/p>

作為一名資深的手機(jī)用戶(我相信人人都是),是時(shí)候該解決這類疑問(wèn)了。這一切都要從人與宇宙的關(guān)系。。??瓤?。。手機(jī)進(jìn)程的概念開(kāi)始說(shuō)起。

在開(kāi)發(fā)文檔中是這么說(shuō)的:當(dāng)一個(gè)應(yīng)用程序啟動(dòng)時(shí)(僅僅只是“啟動(dòng)時(shí)”,并不一定有組件運(yùn)行),就會(huì)產(chǎn)生一個(gè)進(jìn)程。在這個(gè)進(jìn)程中同時(shí)會(huì)創(chuàng)建一個(gè)主線程,使應(yīng)用內(nèi)的任務(wù)開(kāi)始執(zhí)行。Android系統(tǒng)總是盡可能地保留進(jìn)程。舉個(gè)例子,當(dāng)你打開(kāi)qq時(shí),進(jìn)程創(chuàng)建(同時(shí)創(chuàng)建主線程),隨后各種內(nèi)容加載(首先是活動(dòng),然后是各種控件什么的)。當(dāng)你完成操作時(shí),一般都會(huì)按后退鍵(back),直至退出程序。

這里需要注意,一般情況下我們一直按后退是希望應(yīng)用程序關(guān)閉的。然而事實(shí)上這樣做只是關(guān)閉了界面(活動(dòng)),大多數(shù)app的“進(jìn)程”仍會(huì)保留(少數(shù)良心app可以設(shè)置在退出時(shí)“完全關(guān)閉”),占用內(nèi)存以進(jìn)行后臺(tái)任務(wù)。進(jìn)程隨應(yīng)用啟動(dòng)而產(chǎn)生,但往往并不隨著應(yīng)用的“關(guān)閉”而關(guān)閉

所以很多時(shí)候我們看上去關(guān)閉了程序,但其實(shí)它仍在后臺(tái)運(yùn)行?。ù颂幷?qǐng)自行回憶那些困擾你的流氓軟件們)。不過(guò)不必?fù)?dān)心,Android 系統(tǒng)自有一套進(jìn)程管理機(jī)制來(lái)幫你管理后臺(tái)任務(wù)。系統(tǒng)會(huì)根據(jù)應(yīng)用的重要程度把所有進(jìn)程劃歸為幾個(gè)等級(jí),最不重要的進(jìn)程將會(huì)被優(yōu)先關(guān)閉,相對(duì)重要的進(jìn)程將獲得資源來(lái)保留。

那么問(wèn)題來(lái)了----到底如何分辨哪些進(jìn)程重要而哪些不重要呢?

系統(tǒng)當(dāng)然要保證用戶體驗(yàn),所以重要等級(jí)的劃分原則就是要首先滿足用戶當(dāng)前的需求:用戶正在使用的當(dāng)然不能關(guān)閉,而用戶暫時(shí)不需要的,相對(duì)的就沒(méi)那么重要了。

1.Foreground process 前臺(tái)進(jìn)程:也就是用戶正在進(jìn)行操作的進(jìn)程。這樣的進(jìn)程優(yōu)先級(jí)(優(yōu)先保留)最高,最不容易銷毀,因?yàn)樗憩F(xiàn)在屏幕上,直接同用戶進(jìn)行交互,所以只有當(dāng)內(nèi)存資源極度緊張等一些其他極端情況才會(huì)關(guān)閉,表現(xiàn)為“閃退”。我用的第一臺(tái) Android 手機(jī)運(yùn)行內(nèi)存(RAM)只有 290M,多任務(wù)時(shí)經(jīng)常內(nèi)存不足導(dǎo)致程序“閃退”。這手機(jī)我竟然用了兩年,現(xiàn)在想想都佩服我自己hhhh。

不只是界面交互,如果應(yīng)用程序中的服務(wù)(service)組件正在進(jìn)行一些操作或者廣播接收者(BroadcastReceiver)在執(zhí)行接收廣播的操作(onReceive)時(shí),該進(jìn)程仍被視為前臺(tái)進(jìn)程。

2.Visible process 可視進(jìn)程:顧名思義,就是仍然在屏幕上有顯示,但用戶不再能直接與它交互的程序。比如當(dāng)在應(yīng)用中打開(kāi)下滑菜單時(shí)(有些下滑菜單是透明的),用戶能“看得到”,但是“摸不著”。優(yōu)先級(jí)僅次于前臺(tái)進(jìn)程。

3.Service process 服務(wù)進(jìn)程:該進(jìn)程中開(kāi)啟了一個(gè)服務(wù)(通過(guò)startService方法)。注意這里強(qiáng)調(diào)的是服務(wù)的“開(kāi)啟”,區(qū)別于第一類中的“服務(wù)正在執(zhí)行一些操作”。大多數(shù)音樂(lè)軟件都是通過(guò)這種方法來(lái)保留其播放音樂(lè)的進(jìn)程。

4.Background process 后臺(tái)進(jìn)程:當(dāng)你按下 HOME 鍵或 BACK 鍵時(shí),手機(jī)退回主界面,此時(shí)應(yīng)用程序不再可見(jiàn),轉(zhuǎn)入后臺(tái)運(yùn)行。如果如果不滿足前幾類的條件,這個(gè)進(jìn)程就會(huì)被判定為后臺(tái)進(jìn)程。

5.Empty process 空進(jìn)程:A process that doesn't hold any active application components.沒(méi)有任何組件在運(yùn)行,包括活動(dòng)界面(Activity)。事實(shí)上用戶已經(jīng)不再需要這個(gè)進(jìn)程了,但出于 Android 系統(tǒng)“盡可能保留進(jìn)程”的原則,這樣的進(jìn)程出現(xiàn)后不會(huì)被立即銷毀。保留進(jìn)程的唯一理由,就是為了下次開(kāi)啟這個(gè)應(yīng)用時(shí)能快一些。其實(shí)現(xiàn)在的手機(jī)硬件性能足夠好,這樣的緩存對(duì)于用戶體驗(yàn)的提升效果不怎么明顯。這樣的進(jìn)程最不重要,將首先被銷毀。

也許你已經(jīng)注意到了,在屏幕上正在顯示的或者正在服務(wù)于用戶的進(jìn)程的重要等級(jí)是比較高的,這是出于對(duì)用戶體驗(yàn)的考慮-----誰(shuí)會(huì)接受在自己打王者榮耀的時(shí)候游戲突然閃退呢?大多數(shù)情況下,一個(gè)應(yīng)用程序的組件成分都會(huì)比較復(fù)雜,這個(gè)進(jìn)程可能同時(shí)滿足多個(gè)級(jí)別的劃分條件。在這種情況下,它會(huì)被盡可能地劃為能夠達(dá)到的最重要等級(jí)。

如果你的手機(jī)上安裝了好幾個(gè)同一家公司推出的 APP(比如企鵝系、頭條系等),那么當(dāng)你啟動(dòng)其中之一時(shí),剩下的幾款 APP 大概率也會(huì)被喚醒(視軟件的流氓程度而定)。聯(lián)動(dòng)開(kāi)啟的 APP 會(huì)大大占用內(nèi)存,讓手機(jī)變得卡頓。并且它們?cè)S多都需要聯(lián)網(wǎng)服務(wù),占用網(wǎng)速,有些還會(huì)在你不知情(因?yàn)槟悴](méi)有直接開(kāi)啟或使用它們)的情況下監(jiān)控你的數(shù)據(jù)并上傳。

不過(guò),你以為這就完了?

事實(shí)上,如果不手動(dòng)清除,這樣的進(jìn)程很難被系統(tǒng)關(guān)閉,它們會(huì)一直長(zhǎng)期運(yùn)行。這些進(jìn)程大多屬于第三或第四等級(jí),然而如果不同 APP 中的組件構(gòu)成“相互依賴”的關(guān)系,它們所屬進(jìn)程的保留優(yōu)先級(jí)就會(huì)提高,也就越不容易被關(guān)閉。(我等流氓軟件可不是浪得虛名的ε=ε=ε=(  ̄▽ ̄) )

盡管 Android 想要盡可能的保存所有的進(jìn)程,但是并非所有的內(nèi)存都會(huì)被用于維持進(jìn)程。比如系統(tǒng)運(yùn)行會(huì)占用相當(dāng)?shù)膬?nèi)存,系統(tǒng)也需要留出一部分閑置內(nèi)存用以處理新事件。Android 的管理讓內(nèi)存的分配處于一種“動(dòng)態(tài)平衡”中,以保障各項(xiàng)任務(wù)都能盡可能的穩(wěn)定、高效地執(zhí)行。

好了,關(guān)于進(jìn)程的管理就暫時(shí)說(shuō)到這了。眾所周知,Android 系統(tǒng)是一個(gè)復(fù)雜的機(jī)體,它管理著手機(jī)硬件和軟件,讓它們盡可能的配合,提供給用戶最好的服務(wù)。這次只是簡(jiǎn)單介紹了進(jìn)程管理機(jī)制,今后我也會(huì)盡量用通俗的語(yǔ)言從系統(tǒng)上去解釋那些平??瓷先ニ剖嵌堑膯?wèn)題,期待你的關(guān)注!


當(dāng)前標(biāo)題:android進(jìn)程,android 系統(tǒng)進(jìn)程
網(wǎng)站URL:http://weahome.cn/article/hoghje.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部