學習了一下Service,網上常見的一些就不說了,說一下感覺容易給人造成誤解的地方
1. 如Service的建立都是在新進程建立的嗎?
其實不是的,在 Dev Guide中寫道:引用Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking
operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain
dedicated to user interaction with your activities.
就是說,當建立一個Service的時候,預設是在Application的進程裡主UI線程建立的,如果你在Service中進行阻塞的操作,會直接阻塞UI線程,可能導致五秒無響應的提醒,所以官方建議是在Service裡面建立新的線程來防止阻塞放生。
2. 如何在新進程裡建立Service?
一般的方法就是在manifast中聲明Service的時候,使用process標籤,註明所使用的進程,預設使用當前程式主進程:Java代碼
- <service
- android:name="org.foreal.MusicServiceTest"
- android:enabled="true"
- android:process=":music_process"
- ></service>
其中如果進程的名字時以 ":"開頭的,說明進程是當前程式的私人進程,其他程式無法訪問,如果是以小寫字母開頭的進程,說明進程是一個全域的進程,多個程式都可訪問此進程,達到多程式共用進程的目的。
3.如果不用新進程的Service,如何方便的進行一些阻塞操作?
可以繼承IntentService來編寫自己的Service,IntentService會自動建立一個worker thread,來進行操作如:Java代碼
- public class MyIntentService extends IntentService {
-
- private final static String TAG = "MyIntentService";
-
- public MyIntentService() {
- super("MyIntentService");
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- Log.i(TAG, "onHandleIntent");
-
- try {
- synchronized (this){
- wait(3000);
- }
- Log.i(TAG, "完成一次");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
其中只需要重寫onHandleIntent方法來處理自己的操作就行,其中每一次的操作都會進去隊列中,按順序串列執行。
其中要注意的是,IntentService在執行完隊列中所有操作以後會自動銷毀當前Service,也就是說,如果你onHandleIntent中是個非阻塞操作的話,很可能每次調用結束以後Service都被銷毀,然後下次在建立新的Service。
此類可以很方便的完成大多數工作,但是如果要進行並行作業的Service,此類就不適合,應自己實現。
3. 如何使Service私人?
如果在Service中聲明intent filter,那麼其他程式也可以通過你聲明的intent filter來訪問你的Service,為了避免這種情況,首先你可以去掉intent filter,每次調用Service都使用Intent(Context, Class)的形式,但是,如果喜歡用intent filter的形式,可以使用exported標籤,來使Service私人,這樣即使定義intent filter,其他程式也無法訪問。
4.如果一個Service在startService以後 又進行了bindService那麼他的生命週期是怎樣的,stopService能否結束掉Service?
答案是不能的,如果一個Service進行了bind操作,那麼再進行stopService是無法結束掉此Service,知道綁定的Context全部結束,或解除綁定,Service才會被結束。
5. Service 中Onstart方法中,參數startid是什麼意思,又有什麼用處?
因為在使用startService開啟一個Service以後,必須手動的關閉Service,所以Service可能自己調用 stopSelf 方法,來在任務完成的時候結束掉自己。
但是這個時候就會出現一個問題,如果startService調用了2次,那麼就執行了兩次onStart操作,在第一次onStart操作結束以後,Service可能會認為任務已經完成,並結束掉自己,這個時候第二次的onStart可能還沒結束,導致了任務還未完成就被強行關閉了。
而startid代表當前onStart被調用的一個編號,在結束Service時候,調用stopSelf(startid),這樣Service就可以檢查,此startid是否是最近一次調用的,如果是,那麼才結束Service,否則不結束。
如有錯誤,歡迎指出探討。