萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> 安卓開發 >> android 進程的優先級

android 進程的優先級

 進程的優先級

12.1.1.概述
Android規定:進程的優先級分為以下五個級別,如圖-1所示:
圖-1
1、 前台進程 -Activte process
Active (前台) process是包含(與用戶交互的)控件的那種應用程序。這些是Android通過回收資源來極力保護的進程。Active process包括:
(1)處於“active”狀態的Activity,它們運行在前台來響應用戶的事件。
(2)Activity Service或者正在執行onReceive事件處理函數的Broadcast Receiver。
(3)正在執行onStart,onCreate,OnDestroy事件處理函數的Service。
2、 可見進程-Visible Process
可見但不活動的進程是那些擁有“可見”Activity的進程。“可見”Activity是那些在屏幕上可見,但不是在前台或不響應用戶事件的Activity。這種情況發生在當一個Activity被部分遮蓋的時候(被一個非全屏或者透明的Activity)。可見進程只在極端的情況下,才會被殺死來保證Active Process的運行。包括以下情況:
(1)可見的Activity,但處於暫停(onPause()) 狀態;
(2)被可見Activity綁定的Service
3、 服務進程 Service process 
進程中包含已經啟動的Service。Service以動態的方式持續運行但沒有可見的界面。因為Service不直接和用戶交互,它們擁有比visible Process較低的優先級。它們還是可以被認為是前台進程,不會被殺死,直到資源被active/visible Process需求。
4、 背景進程 Background process
進程中的Activity不可見和進程中沒有任何啟動的Service,這些進程都可以看作是後台進程。在系統中,擁有大量的後台進程,並且Android按照後看見先殺掉的原則來殺掉後台進程以獲取資源給前台進程。
5、 空進程-Empty process
為了改善整個系統的性能,Android經常在內存中保留那些已經走完生命周期的應用程序。Android維護這些緩存來改善應用程序重新啟動的時間。這些進程在資源需要的時候常常被殺掉。
當一個進程被殺掉,進程保留,變成空進程。
12.1.2.設置/取消Service為前台進程的方法
由上所述,Service排在進程的第三優先級,通常耗時的操作是放在線程中,那麼將這樣的線程放在Service中將會有較高的優先級,降低被Android系統殺掉的幾率。
若是將線程放在Activity中,當Activity被完全遮蓋,處於onStop狀態時,其進程的優先級別降為第四級。明顯不如放在處於第三級別的Service中更保險。
應用場景,如音樂播放器,通過在前台做其它操作時,音樂播放器在後台播放音樂,這種情況將播放音樂的線程放在Service中是適宜的。
Service類中有兩個方法,分別用來設置Service為前台進程和取消前台進程。被設置為前台進程的Service擁有最高的優先級別,被Android系統殺掉的幾率降至最低。
1、startForeground(int id,Notification noti);
作用:設置Service對象為前台進程。
說明:
第一個參數是通知的id值。

第二個參數是通知對象。
startForegroud方法的參數與通知管理器相同,使用上也類似,都是發送一個通知,並指定該通知對象的id值。
2、stopForeGround(int id);
作用:取消(指定id值所通知的Service對象)前台進程。
12.1.3.設置Service為前台進程的步驟
步驟1、在Service類的onStartCommand方法中(通常在該方法中)創建Intent對象,並指定與其綁定的Activity,示例代碼如下:
Intent foreIntent=new Intent(this, MainActivity.class);
步驟2、創建PendingIntetn對象
PendingIntent pintent=PendingIntent.getActivity(
this, 0, foreIntent, PendingIntent.FLAG_UPDATE_CURRENT);
說明:第四個參數指明在通知欄隨時刷新通知。
步驟3、創建通知對象,示例代碼如下:
Notification noti=new Notification(
R.drawable.icon,"notification",System.currentTimeMillis());
說明:
第一個參數是通知欄中顯示的本通知的圖標。
第二個參數是通知欄中顯示的本通知的標題。
第三個參數是本通知發出的時間。
步驟4、將此通知放到通知欄的(Ongoing)正在運行組中,示例代碼如下:
noti.flags=Notification.FLAG_ONGOING_EVENT;
步驟5、設置通知的點擊事件,示例代碼如下:
noti.setLatestEventInfo(this, "title","content", pintent);
步驟6、向指定的Activity發送通知,並設置當前的Service對象為前台進程,示例代碼如下:
startForeground(97789, noti);
12.1.4.示例
運行圖-1所示的窗口:
圖-2
1、單擊圖-1中的start foreground按鈕,將啟動一個Service對象,並設置改Service為前台進程,在該在日志窗口中出現圖-2中紅框內的第一行信息。
2、單擊圖-2中的stop foreground按鈕,將取消Service的當前進程,並在日志窗口中顯示圖-2中紅框內的第二行信息。
以下列出關鍵代碼:
步驟1、創建項目exer12_01,包名為com.tarena.exer12_01,項目入口:MainActivity類,該中關鍵代碼如下所示:
@Override
public void onClick(View v) {
//創建Intent對象,並設置目標組件為MyService
Intent intent=new Intent();
intent.setClass(this, MyService.class);
switch(v.getId()){
case R.id.btnStartFore:
//設置intent.action的值為Constant.ACTION_FORE
intent.setAction(Constant.ACTION_FORE);
startService(intent);//啟動服務
break;
case R.id.btnStopFore:
//設置intent.action的值為Constant.ACTION_STOP_FORE
intent.setAction(Constant.ACTION_STOP_FORE);
startService(intent);
break;
case R.id.btnStopService:
stopService(intent);//停止服務
break;
}
}
步驟2、在src/com.tarena.exer12_01包下創建MyService.java該類繼承自Service類。關鍵代碼如下所示:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String action=intent.getAction();
if(Constant.ACTION_FORE.equals(action)){
Log.i(tag,"startForeground");
Intent foreIntent=new Intent();
foreIntent.setClass(this, MainActivity.class);
PendingIntent pintent=PendingIntent.getActivity(
this, 0, foreIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification noti=new Notification(
R.drawable.icon,"notification",System.currentTimeMillis());
//將此通知放到通知欄的"Ongoing"即"正在運行"組中

noti.flags=Notification.FLAG_ONGOING_EVENT;
noti.setLatestEventInfo(
this, "改變Service優先級", "設置service為foreground級別", pintent);
startForeground(97789, noti);
}else if(Constant.ACTION_STOP_FORE.equals(action)){
Log.i(tag,"stopForeground");
stopForeground(true);//取消當前服務為前台服務
}
return super.onStartCommand(intent, flags, startId);
}
步驟3、打開項目清單文件,注冊該服務,如下代碼中紅框中代碼所示:
<application android:icon="@drawable/icon" 
android:label="@string/app_name">
<service android:name="MyService"></service>
</application>
12.2.UI與線程
12.2.1.概述
UI是英文User Interface單詞的簡稱。
當應用程序啟動時,系統會為應用程序創建一個主線程(main)或者叫UI線程,它負責分發事件到不同的控件(例如繪畫事件)以完成應用程序與Android UI孔廟件的交互。
例如,當觸摸屏幕上的一個按鈕時,UI線程會把觸摸事件分發到控件上,更改狀態並加入事件隊列,UI線程會分發請求和通知到各個控件,完成相應的動作。
單線程模型的性能是非常差的,除非應用程序相當簡單,特別是當所有的操作都在主線程中執行,比如訪問網絡或數據庫之類的耗時操作將會導致用戶界面鎖定,所有的事件將不能分發,應用程序就像死了一樣,更嚴重的是當超過5秒時,系統就會彈出“應用程序無響應”的對話框。
12.2.2.main線程
主線程也叫UI線程,主線程負責UI的創建,UI的刷新以及處理用戶的輸入事件。
提示:Android規定,Activity中的控件的刷新由主線程負責,其它線程不能直接刷新。
12.2.3.ANR術語
ANR的全稱:Activity or Application is not responding,當用戶操作超過系統規定的響應時間時,會彈出ANR對話框,如圖-3所示:
圖-3
若選擇Force close按鈕將強制關閉當前的Activity;
若選擇Wait按鈕將保留當前的Activity繼續等待。
出現ANR的條件:
1. 在main線程(或稱主線程)中有一個耗時操作正在執行,此時用戶輸入事件並且這個事件在5秒內沒有得到響應,就會彈出ANR。
2. 廣播接收者的onReceive()方法在10秒內沒有執行完成,也會彈出ANR。
提示:在廣播接收者的onReceive方法中要避免執行耗時的操作。
12.2.4.示例-測試ANR發生的兩種情況
創建項目exer12_02,在該

copyright © 萬盛學電腦網 all rights reserved